second big RT integration checkin, customer linking/delinking interface
authorivan <ivan>
Thu, 2 Dec 2004 09:59:48 +0000 (09:59 +0000)
committerivan <ivan>
Thu, 2 Dec 2004 09:59:48 +0000 (09:59 +0000)
23 files changed:
FS/FS/CGI.pm
FS/FS/ClientAPI/Agent.pm
FS/FS/Conf.pm
FS/FS/TicketSystem.pm [new file with mode: 0644]
FS/FS/TicketSystem/RT_Internal.pm
FS/FS/TicketSystem/RT_Libs.pm
FS/FS/cust_main.pm
htetc/global.asa
htetc/handler.pl
httemplate/images/small-logo.png
httemplate/index.html
httemplate/search/cust_main.cgi
rt/FREESIDE_MODIFIED
rt/html/Elements/Header
rt/html/Elements/PageLayout
rt/html/Ticket/Elements/AddCustomers [new file with mode: 0644]
rt/html/Ticket/Elements/EditCustomers [new file with mode: 0644]
rt/html/Ticket/Elements/ShowCustomers [new file with mode: 0644]
rt/html/Ticket/Elements/ShowSummary
rt/html/Ticket/Elements/Tabs
rt/html/Ticket/ModifyCustomers.html [new file with mode: 0644]
rt/lib/RT/Interface/Web_Vendor.pm [new file with mode: 0644]
rt/lib/RT/URI/freeside.pm

index 9b406d3..a4fc42f 100644 (file)
@@ -277,7 +277,7 @@ sub ntable {
 
 }
 
-=item small_custview CUSTNUM || CUST_MAIN_OBJECT, COUNTRYDEFAULT
+=item small_custview CUSTNUM || CUST_MAIN_OBJECT, COUNTRYDEFAULT, NOBALANCE_FLAG
 
 Sheesh. I should just switch to Mason.
 
@@ -289,12 +289,13 @@ sub small_custview {
 
   my $arg = shift;
   my $countrydefault = shift || 'US';
+  my $nobalance = shift;
 
   my $cust_main = ref($arg) ? $arg
                   : qsearchs('cust_main', { 'custnum' => $arg } )
     or die "unknown custnum $arg";
 
-  my $html = 'Customer #<B>'. $cust_main->custnum. '</B>'.
+  my $html = 'Customer #<B>'. $cust_main->custnum. '</B></A>'.
     ' - <B><FONT COLOR="'. $cust_main->statuscolor. '">'.
     ucfirst($cust_main->status). '</FONT></B>'.
     ntable('#e8e8e8'). '<TR><TD>'. ntable("#cccccc",2).
@@ -366,7 +367,8 @@ sub small_custview {
 
   $html .= '</TR></TABLE>';
 
-  $html .= '<BR>Balance: <B>$'. $cust_main->balance. '</B><BR>';
+  $html .= '<BR>Balance: <B>$'. $cust_main->balance. '</B><BR>'
+    unless $nobalance;
 
   # last payment might be good here too?
 
index 1cc11d5..f534a86 100644 (file)
@@ -6,9 +6,9 @@ use strict;
 use vars qw($cache);
 use Digest::MD5 qw(md5_hex);
 use Cache::SharedMemoryCache; #store in db?
-use FS::Record qw(qsearchs qsearch dbdef dbh);
+use FS::Record qw(qsearchs); # qsearch dbdef dbh);
 use FS::agent;
-use FS::cust_main;
+use FS::cust_main qw(smart_search);
 
 use FS::ClientAPI;
 FS::ClientAPI->register_handlers(
@@ -102,68 +102,9 @@ sub agent_list_customers {
   my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
     or return { 'error' => "unknown agentnum $agentnum" };
 
-  my @cust_main = ();
-
-  #warn $p->{'search'};
-  if ( $p->{'search'} =~ /^\s*(\d+)\s*$/ ) { # customer # search
-    push @cust_main, qsearch('cust_main', { 'agentnum' => $agentnum,
-                                            'custnum'  => $1         } );
-  } elsif ( $p->{'search'} =~ /^\s*(\S.*\S)\s*$/ ) { #value search
-    my $value = lc($1);
-    my $q_value = dbh->quote($value);
-
-    #exact
-    my $sql = " AND ( LOWER(last) = $q_value OR LOWER(company) = $q_value";
-    $sql .= " OR LOWER(ship_last) = $q_value OR LOWER(ship_company) = $q_value"
-      if defined dbdef->table('cust_main')->column('ship_last');
-    $sql .= ' )';
-
-    push @cust_main, qsearch( 'cust_main',
-                              { 'agentnum' => $agentnum },
-                              '',
-                              $sql
-                            );
-
-    unless ( @cust_main ) {
-      warn "no exact match, trying substring/fuzzy\n";
-
-      #still some false laziness w/ search/cust_main.cgi
-
-      #substring
-      push @cust_main, qsearch( 'cust_main',
-                                { 'agentnum' => $agentnum,
-                                  'last'     => { 'op'    => 'ILIKE',
-                                                  'value' => "%$q_value%" } } );
-
-      push @cust_main, qsearch( 'cust_main',
-                                { 'agentnum'  => $agentnum,
-                                  'ship_last' => { 'op'    => 'ILIKE',
-                                                   'value' => "%$q_value%" } } )
-        if defined dbdef->table('cust_main')->column('ship_last');
-
-      push @cust_main, qsearch( 'cust_main',
-                                { 'agentnum' => $agentnum,
-                                  'company'  => { 'op'    => 'ILIKE',
-                                                  'value' => "%$q_value%" } } );
-
-      push @cust_main, qsearch( 'cust_main',
-                                { 'agentnum'     => $agentnum,
-                                  'ship_company' => { 'op' => 'ILIKE',
-                                                   'value' => "%$q_value%" } } )
-        if defined dbdef->table('cust_main')->column('ship_last');
-
-      #fuzzy
-      push @cust_main, FS::cust_main->fuzzy_search(
-        { 'last'     => $value },
-        { 'agentnum' => $agentnum }
-      );
-      push @cust_main, FS::cust_main->fuzzy_search(
-        { 'company'  => $value },
-        { 'agentnum' => $agentnum }
-      );
-
-    }
-  }
+  my @cust_main = smart_search( 'search'   => $p->{'search'},
+                                'agentnum' => $agentnum,
+                              );
 
   #aggregate searches
   push @cust_main,
index ccad607..1346796 100644 (file)
@@ -1328,6 +1328,20 @@ httemplate/docs/config.html
     'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
   },
 
+  {
+    'key'         => 'ticket_system-custom_priority_field',
+    'section'     => '',
+    'description' => 'Custom field from the ticketing system to use as a custom priority classification.',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'company_name',
+    'section'     => 'required',
+    'description' => 'Your company name',
+    'type'        => 'text',
+  },
+
 );
 
 1;
diff --git a/FS/FS/TicketSystem.pm b/FS/FS/TicketSystem.pm
new file mode 100644 (file)
index 0000000..2a5c68f
--- /dev/null
@@ -0,0 +1,30 @@
+package FS::TicketSystem;
+
+use strict;
+use vars qw( $system $AUTOLOAD );
+use FS::Conf;
+use FS::UID;
+
+install_callback FS::UID sub { 
+  my $conf = new FS::Conf;
+  $system = $conf->config('ticket_system');
+};
+
+sub AUTOLOAD {
+  my $self = shift;
+
+  my($sub)=$AUTOLOAD;
+  $sub =~ s/.*://;
+
+  my $conf = new FS::Conf;
+  die "FS::TicketSystem::$AUTOLOAD called, but no ticket system configured\n"
+    unless $system;
+
+  eval "use FS::TicketSystem::$system;";
+  die $@ if $@;
+
+  $self .= "::$system";
+  $self->$sub(@_);
+}
+
+1;
index a4ecd6a..ec0c3f7 100644 (file)
@@ -1,8 +1,17 @@
 package FS::TicketSystem::RT_Internal;
 
 use strict;
+use vars qw( @ISA );
 
 @ISA = qw( FS::TicketSystem::RT_Libs );
 
+sub sql_customer_tickets {
+  "( select count(*) from tickets
+                     join links on ( tickets.id = links.localbase )
+     where ( status = 'new' or status = 'open' or status = 'stalled' )
+       and target = 'freeside://freeside/cust_main/' || custnum
+   )";
+}
+
 1;
 
index b717632..aba783f 100644 (file)
@@ -1,6 +1,7 @@
 package FS::TicketSystem::RT_Libs.pm
 
 use strict;
+use vars qw( @ISA );
 
 @ISA = qw( FS::TicketSystem::RT_External );
 
index d8dbd52..27f97f3 100644 (file)
@@ -1,10 +1,11 @@
 package FS::cust_main;
 
 use strict;
-use vars qw( @ISA $conf $DEBUG $import );
+use vars qw( @ISA @EXPORT_OK $conf $DEBUG $import );
 use vars qw( $realtime_bop_decline_quiet ); #ugh
 use Safe;
 use Carp;
+use Exporter;
 BEGIN {
   eval "use Time::Local;";
   die "Time::Local minimum version 1.05 required with Perl versions before 5.6"
@@ -43,6 +44,8 @@ use FS::Msgcat qw(gettext);
 
 @ISA = qw( FS::Record );
 
+@EXPORT_OK = qw( smart_search );
+
 $realtime_bop_decline_quiet = 0;
 
 $DEBUG = 0;
@@ -2977,6 +2980,94 @@ sub fuzzy_search {
 
 =over 4
 
+=item smart_search OPTION => VALUE ...
+
+Accepts the following options: I<search>, the string to search for.  The string
+will be searched for as a customer number, last name or company name, first
+searching for an exact match then fuzzy and substring matches.
+
+Any additional options treated as an additional qualifier on the search
+(i.e. I<agentnum>).
+
+Returns a (possibly empty) array of FS::cust_main objects.
+
+=cut
+
+sub smart_search {
+  my %options = @_;
+  my $search = delete $options{'search'};
+  my @cust_main = ();
+
+  if ( $search =~ /^\s*(\d+)\s*$/ ) { # customer # search
+
+    push @cust_main, qsearch('cust_main', { 'custnum' => $1, %options } );
+
+  } elsif ( $search =~ /^\s*(\S.*\S)\s*$/ ) { #value search
+
+    my $value = lc($1);
+    my $q_value = dbh->quote($value);
+
+    #exact
+    my $sql = scalar(keys %options) ? ' AND ' : ' WHERE ';
+    $sql .= " ( LOWER(last) = $q_value OR LOWER(company) = $q_value";
+    $sql .= " OR LOWER(ship_last) = $q_value OR LOWER(ship_company) = $q_value"
+      if defined dbdef->table('cust_main')->column('ship_last');
+    $sql .= ' )';
+
+    push @cust_main, qsearch( 'cust_main', \%options, '', $sql );
+
+    unless ( @cust_main ) {  #no exact match, trying substring/fuzzy
+
+      #still some false laziness w/ search/cust_main.cgi
+
+      #substring
+      push @cust_main, qsearch( 'cust_main',
+                                { 'last'     => { 'op'    => 'ILIKE',
+                                                  'value' => "%$q_value%" },
+                                  %options,
+                                }
+                              );
+      push @cust_main, qsearch( 'cust_main',
+                                { 'ship_last' => { 'op'    => 'ILIKE',
+                                                   'value' => "%$q_value%" },
+                                  %options,
+
+                                }
+                              )
+        if defined dbdef->table('cust_main')->column('ship_last');
+
+      push @cust_main, qsearch( 'cust_main',
+                                { 'company'  => { 'op'    => 'ILIKE',
+                                                  'value' => "%$q_value%" },
+                                  %options,
+                                }
+                              );
+      push @cust_main, qsearch( 'cust_main',
+                                { 'ship_company' => { 'op' => 'ILIKE',
+                                                   'value' => "%$q_value%" },
+                                  %options,
+                                }
+                              )
+        if defined dbdef->table('cust_main')->column('ship_last');
+
+      #fuzzy
+      push @cust_main, FS::cust_main->fuzzy_search(
+        { 'last'     => $value },
+        \%options,
+      );
+      push @cust_main, FS::cust_main->fuzzy_search(
+        { 'company'  => $value },
+        \%options,
+      );
+
+    }
+
+  }
+
+  @cust_main;
+
+}
+
 =item check_and_rebuild_fuzzyfiles
 
 =cut
index 5cfcca6..612f6f4 100644 (file)
@@ -32,6 +32,7 @@ use FS::CGI qw(header menubar popurl table itable ntable idiot eidiot
 use FS::Msgcat qw(gettext geterror);
 use FS::Misc qw( send_email );
 use FS::Report::Table::Monthly;
+use FS::TicketSystem;
 
 use FS::agent;
 use FS::agent_type;
index a17aff1..c91a0ec 100644 (file)
@@ -115,6 +115,7 @@ sub handler
       use FS::Msgcat qw(gettext geterror);
       use FS::Misc qw( send_email );
       use FS::Report::Table::Monthly;
+      use FS::TicketSystem;
 
       use FS::agent;
       use FS::agent_type;
@@ -123,7 +124,7 @@ sub handler
       use FS::cust_bill_pay;
       use FS::cust_credit;
       use FS::cust_credit_bill;
-      use FS::cust_main;
+      use FS::cust_main qw(smart_search);
       use FS::cust_main_county;
       use FS::cust_pay;
       use FS::cust_pkg;
index a8fe807..1e415e6 100644 (file)
Binary files a/httemplate/images/small-logo.png and b/httemplate/images/small-logo.png differ
index 6283c22..360cc55 100644 (file)
@@ -13,7 +13,7 @@
         <IMG BORDER=0 ALT="freeside" SRC="images/small-logo.png">
       </td>
       <td align=left rowspan=2> <!-- valign="top" -->
-        <font size=7>Billing</font>
+        <font size=6><%= $conf->config('company_name') %> Billing</font>
       </td>
       <td align=right valign=top>Logged in as <b><%= getotaker %></b>
       </td>
@@ -25,8 +25,7 @@
           <tr>
             <td align=right>
               <FONT SIZE="-2">
-               Freeside <%= $FS::VERSION %><BR>
-               <A HREF="http://www.sisd.com/freeside">Freeside&nbsp;home&nbsp;page</A><BR>
+               <A HREF="http://www.sisd.com/freeside">Freeside</A>&nbsp;v<%= $FS::VERSION %><BR>
                <A HREF="docs/">Documentation</A><BR>
               </FONT>
             </td>
@@ -35,8 +34,7 @@
               <td bgcolor=#000000></td>
               <td align=left>
                 <FONT SIZE="-2">
-                 RT <%= $RT::VERSION %><BR>
-                 <A HREF="http://www.bestpractical.com/rt">RT&nbsp;home&nbsp;page</A><BR>
+                 <A HREF="http://www.bestpractical.com/rt">RT<A>&nbsp;v<%= $RT::VERSION %><BR>
                  <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR>
                 </FONT>
               </td>
     <TR><TD>
         <BR><FONT SIZE="+1"><A HREF="rt/">Ticketing Main</A></FONT>
         <BR>
+        <UL>
+          <LI><A HREF="search/cust_main.cgi?browse=tickets">Customers sorted by active tickets</A>
+          <LI><A HREF="">Active tickets not assigned to a customer</A>
+          <LI>
     </TD></TR>
     </TABLE>
 
index 27f23de..c4b0ce0 100755 (executable)
@@ -48,6 +48,9 @@ $limit .= " OFFSET $offset" if $offset;
 my $total = 0;
 
 my(@cust_main, $sortby, $orderby);
+my @select = ();
+my @addl_headers = ();
+my @addl_cols = ();
 if ( $cgi->param('browse')
      || $cgi->param('otaker_on')
      || $cgi->param('agentnum_on')
@@ -65,6 +68,12 @@ if ( $cgi->param('browse')
     } elsif ( $query eq 'company' ) {
       $sortby=\*company_sort;
       $orderby = "ORDER BY LOWER(company || ' ' || last || ' ' || first )";
+    } elsif ( $query eq 'tickets' ) {
+      $sortby = \*tickets_sort;
+      $orderby = "ORDER BY tickets DESC";
+      push @select, FS::TicketSystem->sql_customer_tickets. " as tickets";
+      push @addl_headers, 'Tickets';
+      push @addl_cols, 'tickets';
     } else {
       die "unknown browse field $query";
     }
@@ -136,7 +145,14 @@ if ( $cgi->param('browse')
     }
   }
 
-  @cust_main = qsearch('cust_main', \%search, '',   
+  my $select;
+  if ( @select ) {
+    $select = 'cust_main.*, '. join (', ', @select);
+  } else {
+    $select = '*';
+  }
+
+  @cust_main = qsearch('cust_main', \%search, $select,   
                          "$addl_qual $orderby $limit" );
 
 #  foreach my $cust_main ( @just_cust_main ) {
@@ -312,6 +328,10 @@ if ( defined dbdef->table('cust_main')->column('ship_last') ) {
 END
 }
 
+foreach my $addl_header ( @addl_headers ) {
+  print "<TH>$addl_header</TH>";
+}
+
 print <<END;
         <TH>Packages</TH>
         <TH COLSPAN=2>Services</TH>
@@ -370,6 +390,12 @@ END
 END
     }
 
+    foreach my $addl_col ( @addl_cols ) {
+      print qq!<TD ROWSPAN=$rowspan><A HREF="XXXnotyetXXX">!.
+              $cust_main->get($addl_col).
+            "</A></TD>";
+    }
+
     my($n1)='';
     foreach ( @{$all_pkgs{$custnum}} ) {
       my $pkgnum = $_->pkgnum;
@@ -424,6 +450,10 @@ sub custnum_sort {
   $a->getfield('custnum') <=> $b->getfield('custnum');
 }
 
+sub tickets_sort {
+  $a->getfield('tickets') <=> $b->getfield('tickets');
+}
+
 sub custnumsearch {
 
   my $custnum = $cgi->param('custnum_text');
index 1f3f55c..67bcfec 100644 (file)
@@ -3,11 +3,18 @@ sbin/rt-setup-database.in
 config.layout
 config.layout.in
 etc/RT_SiteConfig.pm
+lib/RT/Interface/Web_Vendor.pm
 lib/RT/URI/freeside.pm
 html/Elements/Header
 html/Elements/PageLayout
 html/Elements/SimpleSearch
 html/Elements/Tabs
 html/Elements/Footer
+html/Ticket/Elements/AddCustomers
+html/Ticket/Elements/EditCustomers
+html/Ticket/Elements/ShowCustomers
+html/Ticket/Elements/ShowSummary
+html/Ticket/Elements/Tabs
+html/Ticket/ModifyCustomers.html
 html/NoAuth/images/small-logo.png
 html/NoAuth/webrt.css
index 92c186b..38cb4bd 100644 (file)
@@ -43,7 +43,7 @@ ONLOAD="
 <table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF">
   <tr> 
     <td rowspan=2><img border=0 alt="freeside" src="<%$RT::WebImagesURL%>/small-logo.png" width="92" height="62"></td>
-    <td align="left" rowspan=2><font size=7>Ticketing</font></td>
+    <td align="left" rowspan=2><font size=6><% FS::Conf->new->config('company_name') %> Ticketing</font></td>
     <td align="right" valign="top">
 % if ($session{'CurrentUser'} && $session{'CurrentUser'}->Id && $LoggedIn) {
 <SPAN STYLE="display: none"><A HREF="#skipnav"><&|/l&>Skip Menu</&></A> |</SPAN>
@@ -67,16 +67,14 @@ ONLOAD="
         <tr>
           <td align=right>
             <FONT SIZE="-3">
-             Freeside <% $FS::VERSION %><BR>
-             <A HREF="http://www.sisd.com/freeside">Freeside&nbsp;home&nbsp;page</A><BR>
+              <A HREF="http://www.sisd.com/freeside">Freeside</A>&nbsp;v<% $FS::VERSION %><BR>
              <A HREF="docs/">Documentation</A><BR>
             </FONT>
           </td>
           <td bgcolor=#000000></td>
           <td align=left>
             <FONT SIZE="-3">
-             RT <% $RT::VERSION %><BR>
-             <A HREF="http://www.bestpractical.com/rt">RT&nbsp;home&nbsp;page</A><BR>
+             <A HREF="http://www.bestpractical.com/rt">RT</A>&nbsp;v<% $RT::VERSION %><BR>
              <A HREF="http://wiki.bestpractical.com/">Documentation</A><BR>
             </FONT>
           </td>
index 86b6b56..6146b80 100644 (file)
@@ -46,7 +46,7 @@
 </td>
 </tr>
 <tr>
-<td class="whiteright" valign="top">
+<td class="mediumgrayright" valign="top">
     <span class="nav"> 
 % if ($actions) {
 % my @actions;
diff --git a/rt/html/Ticket/Elements/AddCustomers b/rt/html/Ticket/Elements/AddCustomers
new file mode 100644 (file)
index 0000000..b26b3a6
--- /dev/null
@@ -0,0 +1,65 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<BR>
+<%$msg%><br>
+
+% if (@Customers) {
+
+<br><i>(Check box to link)<i>
+<table>
+% foreach my $customer (@Customers) {
+<tr>
+  <td>
+    <input type="checkbox" name="Ticket-AddCustomer-<% $customer->custnum %>" VALUE="1" <% scalar(@Customers) == 1 ? 'CHECKED' : '' %>>
+%#    <% $customer->name %>
+    <A HREF="<% $p %>view/cust_main.cgi?<% $customer->custnum %>"><% small_custview( $customer, scalar(FS::Conf->new->config('countrydefault')), 1 ) |n %>
+  </td>
+</tr>
+% }
+
+% }
+
+<%INIT>
+my ($msg);
+
+my @Customers = ();
+if ( $CustomerString ) {
+    @Customers = smart_search( 'search' => $CustomerString );
+    warn scalar(@Customers);
+}
+
+my @Services = ();
+if ($ServiceString) {
+    @Services = (); #service_search();
+}
+
+eval { use FS::CGI qw( popurl small_custview ); };
+my $p = eval { popurl(3); };
+
+</%INIT>
+
+<%ARGS>
+$CustomerString => undef
+$ServiceString => undef
+</%ARGS>
diff --git a/rt/html/Ticket/Elements/EditCustomers b/rt/html/Ticket/Elements/EditCustomers
new file mode 100644 (file)
index 0000000..49edb27
--- /dev/null
@@ -0,0 +1,79 @@
+%# BEGIN LICENSE BLOCK
+%# 
+%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%# 
+%# (Except where explictly superceded by other copyright notices)
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# Unless otherwise specified, all modifications, corrections or
+%# extensions to this work which alter its source code become the
+%# property of Best Practical Solutions, LLC when submitted for
+%# inclusion in the work.
+%# 
+%# 
+%# END LICENSE BLOCK
+<TABLE width=100%>
+  <TR>
+    <TD VALIGN=TOP WIDTH=50%>
+      <h3><&|/l&>Current Customers</&></h3>
+
+<table>
+  <tr>
+    <td><i><&|/l&>(Check box to disassociate)</&></i></td>
+  </tr>
+  <tr>
+    <td class="value">
+% #while (my $link = $Ticket->MemberOf->Next) {
+% foreach my $link (
+%   grep { $_->TargetURI->Resolver->{'fstable'} eq 'cust_main' }
+%   grep { $_->TargetURI->Scheme eq 'freeside' }
+%        @{ $Ticket->_Links('Base')->ItemsArrayRef }
+% ) {
+
+      <INPUT TYPE=CHECKBOX NAME="DeleteLink--<%$link->Type%>-<%$link->Target%>">
+%#        <& ShowLink, URI => $link->TargetURI &><br>
+        <A HREF="<% $link->TargetURI->Resolver->HREF %>"><% $link->TargetURI->Resolver->AsStringLong |n %>
+      <BR>
+% }
+    </td>
+  </tr>
+</table>
+                           
+</TD>
+
+<TD VALIGN=TOP>
+<h3><&|/l&>New Customer Links</&></h3>
+<&|/l&>Find customer</&><BR>
+<input name="CustomerString">
+<input type=submit name="OnlySearchForCustomers" value="<&|/l&>Go!</&>">
+<br><i>cust #, last name, or company</i>
+<BR>
+%#<BR>
+%#<&|/l&>Find service</&><BR>
+%#<input name="ServiceString">
+%#<input type=submit name="OnlySearchForServices" value="<&|/l&>Go!</&>">
+%#<br><i>username, username@domain, domain, or IP address</i>
+%#<BR>
+
+<& AddCustomers, Ticket         => $Ticket,
+                 CustomerString => $CustomerString,
+                 ServiceString  => $ServiceString,  &>
+
+</TD>
+</TR>
+</TABLE>
+      
+<%ARGS>
+$CustomerString => undef
+$ServiceString => undef
+$Ticket => undef
+</%ARGS>
diff --git a/rt/html/Ticket/Elements/ShowCustomers b/rt/html/Ticket/Elements/ShowCustomers
new file mode 100644 (file)
index 0000000..5519d24
--- /dev/null
@@ -0,0 +1,40 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+<table>
+% my $cust = 0;
+% foreach my $customerURI (
+%   grep { $_->Resolver->{'fstable'} eq 'cust_main' }
+%   grep { $_->Scheme eq 'freeside' }
+%    map { $_->TargetURI }
+%        @{ $Ticket->_Links('Base')->ItemsArrayRef }
+% ) {
+%   $cust++;
+%   my $cust_main = '';
+  <tr>
+    <td class="value">
+      <A HREF="<% $customerURI->Resolver->HREF %>"><% $customerURI->Resolver->AsStringLong |n %>
+    </td>
+  </tr>
+% }
+% unless ( $cust ) {
+  <tr>
+    <td class="labeltop">
+      <i>(none)<i>
+    </td>
+  </tr>
+
+% }
+</table>
+<%ARGS>
+$Ticket => undef
+</%ARGS>
+
index 5bcc94b..1b9f629 100644 (file)
                color => "#333399" &>
          <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
          <& /Elements/TitleBoxEnd &>
+         <br>
+
+         <& /Elements/TitleBoxStart, title => loc('Customers'),
+               title_href =>"$RT::WebPath/Ticket/ModifyCustomers.html?id=".$Ticket->Id,
+               title_class=> 'inverse',
+               color => "#7f007b" &>
+          <& /Ticket/Elements/ShowCustomers, Ticket => $Ticket &>
+          <& /Elements/TitleBoxEnd &>
+
        <BR>
        </TD>
        <TD VALIGN=TOP WIDTH="50%">
index cba45df..26b2527 100644 (file)
@@ -101,6 +101,8 @@ my $ticket_page_tabs = {
       { title => loc('People'), path => "Ticket/ModifyPeople.html?id=" . $id, },
     _E => { title => loc('Links'),
             path  => "Ticket/ModifyLinks.html?id=" . $id, },
+    _Eb=> { title => loc('Customers'),
+            path  => "Ticket/ModifyCustomers.html?id=" . $id, },
     _F => { title => loc('Jumbo'),
             path  => "Ticket/ModifyAll.html?id=" . $id,
             seperator => 1
diff --git a/rt/html/Ticket/ModifyCustomers.html b/rt/html/Ticket/ModifyCustomers.html
new file mode 100644 (file)
index 0000000..72d103b
--- /dev/null
@@ -0,0 +1,49 @@
+%# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+<& /Elements/Header, Title => loc("Customers for ticket #[_1]", $Ticket->Id) &>
+<& /Ticket/Elements/Tabs, 
+    Ticket => $Ticket, 
+    current_tab => "Ticket/ModifyCustomers.html?id=".$Ticket->Id, 
+    Title => loc("Customers for ticket #[_1]", $Ticket->Id) &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<form action="ModifyCustomers.html" method="post">
+<input type="hidden" name="id" value="<%$Ticket->id%>">
+
+<& /Elements/TitleBoxStart, title => loc('Edit Customer Links'), color => "#7f007b"&>
+<& Elements/EditCustomers, Ticket => $Ticket, CustomerString => $CustomerString, ServiceString => $ServiceString &>
+<& /Elements/TitleBoxEnd &>
+<& /Elements/Submit, color => "#7f007b", Label => loc('Save Changes') &>
+</form>
+
+
+<%INIT>
+
+my @results = ();
+my $Ticket = LoadTicket($id);
+
+# if we're trying to search for customers/services and nothing else
+unless ( $OnlySearchForCustomers || $OnlySearchForServices) {
+   @results = ProcessTicketCustomers( TicketObj => $Ticket, ARGSRef => \%ARGS);
+}
+    
+</%INIT>
+
+
+<%ARGS>
+$OnlySearchForCustomers => undef
+$OnlySearchForServices => undef
+$CustomerString => undef
+$ServiceString => undef
+$id => undef
+</%ARGS>
diff --git a/rt/lib/RT/Interface/Web_Vendor.pm b/rt/lib/RT/Interface/Web_Vendor.pm
new file mode 100644 (file)
index 0000000..5be20e6
--- /dev/null
@@ -0,0 +1,95 @@
+# Copyright (c) 2004 Ivan Kohler <ivan-rt@420.am>
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+# 
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+
+=head1 NAME
+
+RT::Interface::Web_Vendor
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+Freeside vendor overlay for RT::Interface::Web.
+
+=begin testing
+
+use_ok(RT::Interface::Web_Vendor);
+
+=end testing
+
+=cut
+
+#package RT::Interface::Web;
+#use strict;
+
+package HTML::Mason::Commands;
+use strict;
+
+=head2 ProcessTicketCustomers 
+
+=cut
+
+sub ProcessTicketCustomers {
+    my %args = (
+        TicketObj => undef,
+        ARGSRef   => undef,
+        @_
+    );
+    my @results = ();
+
+    my $Ticket  = $args{'TicketObj'};
+    my $ARGSRef = $args{'ARGSRef'};
+
+    ### false laziness w/RT::Interface::Web::ProcessTicketLinks
+    # Delete links that are gone gone gone.
+    foreach my $arg ( keys %$ARGSRef ) {
+        if ( $arg =~ /DeleteLink-(.*?)-(DependsOn|MemberOf|RefersTo)-(.*)$/ ) {
+            my $base   = $1;
+            my $type   = $2;
+            my $target = $3;
+
+            push @results,
+              "Trying to delete: Base: $base Target: $target  Type $type";
+            my ( $val, $msg ) = $Ticket->DeleteLink( Base   => $base,
+                                                     Type   => $type,
+                                                     Target => $target );
+
+            push @results, $msg;
+
+        }
+
+    }
+    ###
+
+    my @delete_custnums =
+      map  { /^Ticket-AddCustomer-(\d+)$/; $1 }
+      grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} }
+      keys %$ARGSRef;
+
+    my @custnums = map  { /^Ticket-AddCustomer-(\d+)$/; $1 }
+                   grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} }
+                   keys %$ARGSRef;
+
+    foreach my $custnum ( @custnums ) {
+      my( $val, $msg ) =
+        $Ticket->AddLink( 'Type'   => 'MemberOf',
+                          'Target' => "freeside://freeside/cust_main/$custnum",
+                        );
+      push @results, $msg;
+    }
+
+    return @results;
+
+}
+
+1;
+
index bfb514d..ebd24ad 100644 (file)
@@ -82,10 +82,11 @@ sub FreesideURILabel {
         $label = "Freeside service ${svc}: ${tag}";
       }
     } elsif ($table eq 'cust_main') {
-      my ($last, $first, $company) = map { $rec->getfield($_) }
-                                         qw(last first company);
-      $label = "Freeside customer ${last}, ${first}";
-      $label .= ($company ne '') ? " with ${company}" : '';
+      #my ($last, $first, $company) = map { $rec->getfield($_) }
+      #                                   qw(last first company);
+      #$label = "Freeside customer ${last}, ${first}";
+      #$label .= ($company ne '') ? " with ${company}" : '';
+      $label = "$pkey: ". $rec->name;
     } else {
       $label = "Freeside ${table}, ${pkeyfield} == ${pkey}";
     }
@@ -103,6 +104,61 @@ sub FreesideURILabel {
 
 }
 
+sub FreesideURILabelLong {
+
+  my $self = shift;
+
+  return(undef) unless (exists($self->{'fstable'}) and
+                        exists($self->{'fspkey'}));
+
+  my $label;
+  my ($table, $pkey) = ($self->{'fstable'}, $self->{'fspkey'});
+
+  eval {
+    use FS::UID qw(dbh);
+    use FS::Record qw(qsearchs qsearch dbdef);
+    eval "use FS::$table;";
+    use FS::cust_svc;
+
+    my $dbdef = dbdef or die "No dbdef";
+    my $pkeyfield = $dbdef->table($table)->primary_key
+      or die "No primary key for table $table";
+
+    my $rec = qsearchs($table, { $pkeyfield => $pkey })
+      or die "Record with $pkeyfield == $pkey does not exist in table $table";
+
+    if ($table =~ /^svc_/) {
+      #if ($rec->can('cust_svc')) {
+      #  my $cust_svc = $rec->cust_svc or die '$rec->cust_svc failed';
+      #  my ($svc, $tag, $svcdb) = $cust_svc->label;
+      #  $label = "Freeside service ${svc}: ${tag}";
+      #}
+      $label = '';
+    } elsif ($table eq 'cust_main') {
+      use FS::CGI qw(small_custview);
+      $label = small_custview( $rec,
+                               scalar(FS::Conf->new->config('countrydefault')),
+                               1 #nobalance
+                             );
+    } else {
+      #$label = "Freeside ${table}, ${pkeyfield} == ${pkey}";
+      $label = '';
+    }
+
+    #... other cases
+
+  };
+
+  if ($label and !$@) {
+    return($label);
+  } else {
+    warn $@;
+    return(undef);
+  }
+      
+
+}
+
 sub ParseURI { 
     my $self = shift;
     my $uri = shift;
@@ -180,6 +236,22 @@ sub AsString {
     }
 }
 
+=head2 AsStringLong
+
+Return a longer (HTML) string representing the URI object.
+
+=cut
+
+sub AsStringLong {
+    my $self = shift;
+    my $prettystring;
+    if ($prettystring = $self->FreesideURILabelLong || $self->FreesideURILabel){
+      return $prettystring;
+    } else {
+      return $self->URI;
+    }
+}
+
 eval "require RT::URI::base_Vendor";
 die $@ if ($@ && $@ !~ qr{^Can't locate RT/URI/base_Vendor.pm});
 eval "require RT::URI::base_Local";