summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan>2004-12-02 09:59:48 +0000
committerivan <ivan>2004-12-02 09:59:48 +0000
commit0d1d2630e726ab4ce32bab9c3e4a889eee43fcb4 (patch)
tree34d6d7d9dc3ed2ab2bd5fafb585330fc20355b53
parentb81d94452ba28c79036ab417bd32df54a583f324 (diff)
second big RT integration checkin, customer linking/delinking interface
-rw-r--r--FS/FS/CGI.pm8
-rw-r--r--FS/FS/ClientAPI/Agent.pm69
-rw-r--r--FS/FS/Conf.pm14
-rw-r--r--FS/FS/TicketSystem.pm30
-rw-r--r--FS/FS/TicketSystem/RT_Internal.pm9
-rw-r--r--FS/FS/TicketSystem/RT_Libs.pm1
-rw-r--r--FS/FS/cust_main.pm93
-rw-r--r--htetc/global.asa1
-rw-r--r--htetc/handler.pl3
-rw-r--r--httemplate/images/small-logo.pngbin5261 -> 4887 bytes
-rw-r--r--httemplate/index.html12
-rwxr-xr-xhttemplate/search/cust_main.cgi32
-rw-r--r--rt/FREESIDE_MODIFIED7
-rw-r--r--rt/html/Elements/Header8
-rw-r--r--rt/html/Elements/PageLayout2
-rw-r--r--rt/html/Ticket/Elements/AddCustomers65
-rw-r--r--rt/html/Ticket/Elements/EditCustomers79
-rw-r--r--rt/html/Ticket/Elements/ShowCustomers40
-rw-r--r--rt/html/Ticket/Elements/ShowSummary9
-rw-r--r--rt/html/Ticket/Elements/Tabs2
-rw-r--r--rt/html/Ticket/ModifyCustomers.html49
-rw-r--r--rt/lib/RT/Interface/Web_Vendor.pm95
-rw-r--r--rt/lib/RT/URI/freeside.pm80
23 files changed, 623 insertions, 85 deletions
diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm
index 9b406d3..a4fc42f 100644
--- a/FS/FS/CGI.pm
+++ b/FS/FS/CGI.pm
@@ -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?
diff --git a/FS/FS/ClientAPI/Agent.pm b/FS/FS/ClientAPI/Agent.pm
index 1cc11d5..f534a86 100644
--- a/FS/FS/ClientAPI/Agent.pm
+++ b/FS/FS/ClientAPI/Agent.pm
@@ -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,
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index ccad607..1346796 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -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
index 0000000..2a5c68f
--- /dev/null
+++ b/FS/FS/TicketSystem.pm
@@ -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;
diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm
index a4ecd6a..ec0c3f7 100644
--- a/FS/FS/TicketSystem/RT_Internal.pm
+++ b/FS/FS/TicketSystem/RT_Internal.pm
@@ -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;
diff --git a/FS/FS/TicketSystem/RT_Libs.pm b/FS/FS/TicketSystem/RT_Libs.pm
index b717632..aba783f 100644
--- a/FS/FS/TicketSystem/RT_Libs.pm
+++ b/FS/FS/TicketSystem/RT_Libs.pm
@@ -1,6 +1,7 @@
package FS::TicketSystem::RT_Libs.pm
use strict;
+use vars qw( @ISA );
@ISA = qw( FS::TicketSystem::RT_External );
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index d8dbd52..27f97f3 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -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
diff --git a/htetc/global.asa b/htetc/global.asa
index 5cfcca6..612f6f4 100644
--- a/htetc/global.asa
+++ b/htetc/global.asa
@@ -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;
diff --git a/htetc/handler.pl b/htetc/handler.pl
index a17aff1..c91a0ec 100644
--- a/htetc/handler.pl
+++ b/htetc/handler.pl
@@ -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;
diff --git a/httemplate/images/small-logo.png b/httemplate/images/small-logo.png
index a8fe807..1e415e6 100644
--- a/httemplate/images/small-logo.png
+++ b/httemplate/images/small-logo.png
Binary files differ
diff --git a/httemplate/index.html b/httemplate/index.html
index 6283c22..360cc55 100644
--- a/httemplate/index.html
+++ b/httemplate/index.html
@@ -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>
@@ -93,6 +91,10 @@
<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>
diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi
index 27f23de..c4b0ce0 100755
--- a/httemplate/search/cust_main.cgi
+++ b/httemplate/search/cust_main.cgi
@@ -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');
diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED
index 1f3f55c..67bcfec 100644
--- a/rt/FREESIDE_MODIFIED
+++ b/rt/FREESIDE_MODIFIED
@@ -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
diff --git a/rt/html/Elements/Header b/rt/html/Elements/Header
index 92c186b..38cb4bd 100644
--- a/rt/html/Elements/Header
+++ b/rt/html/Elements/Header
@@ -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>
diff --git a/rt/html/Elements/PageLayout b/rt/html/Elements/PageLayout
index 86b6b56..6146b80 100644
--- a/rt/html/Elements/PageLayout
+++ b/rt/html/Elements/PageLayout
@@ -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
index 0000000..b26b3a6
--- /dev/null
+++ b/rt/html/Ticket/Elements/AddCustomers
@@ -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
index 0000000..49edb27
--- /dev/null
+++ b/rt/html/Ticket/Elements/EditCustomers
@@ -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
index 0000000..5519d24
--- /dev/null
+++ b/rt/html/Ticket/Elements/ShowCustomers
@@ -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>
+
diff --git a/rt/html/Ticket/Elements/ShowSummary b/rt/html/Ticket/Elements/ShowSummary
index 5bcc94b..1b9f629 100644
--- a/rt/html/Ticket/Elements/ShowSummary
+++ b/rt/html/Ticket/Elements/ShowSummary
@@ -47,6 +47,15 @@
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%">
diff --git a/rt/html/Ticket/Elements/Tabs b/rt/html/Ticket/Elements/Tabs
index cba45df..26b2527 100644
--- a/rt/html/Ticket/Elements/Tabs
+++ b/rt/html/Ticket/Elements/Tabs
@@ -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
index 0000000..72d103b
--- /dev/null
+++ b/rt/html/Ticket/ModifyCustomers.html
@@ -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
index 0000000..5be20e6
--- /dev/null
+++ b/rt/lib/RT/Interface/Web_Vendor.pm
@@ -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;
+
diff --git a/rt/lib/RT/URI/freeside.pm b/rt/lib/RT/URI/freeside.pm
index bfb514d..ebd24ad 100644
--- a/rt/lib/RT/URI/freeside.pm
+++ b/rt/lib/RT/URI/freeside.pm
@@ -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";