summaryrefslogtreecommitdiff
path: root/rt/share
diff options
context:
space:
mode:
authormark <mark>2012-02-19 00:34:44 +0000
committermark <mark>2012-02-19 00:34:44 +0000
commite010976ba33c00bb2b97d677f610e4b19571feaf (patch)
tree38df4dd0e9f525829fb7373b7783442a9d8170a1 /rt/share
parente67988848e92af19719fe7c06c589e3b7b46d058 (diff)
improve customer field access in RT queries, #16490
Diffstat (limited to 'rt/share')
-rw-r--r--rt/share/html/Callbacks/SearchCustomerFields/Search/Elements/PickBasics/Default59
-rw-r--r--rt/share/html/Elements/CustomerFields215
-rw-r--r--rt/share/html/Elements/RT__Ticket/ColumnMap95
-rw-r--r--rt/share/html/Elements/SelectCustomerAgent17
-rw-r--r--rt/share/html/Elements/SelectCustomerClass17
-rw-r--r--rt/share/html/Elements/SelectCustomerReferral17
-rw-r--r--rt/share/html/Elements/SelectCustomerTag17
-rw-r--r--rt/share/html/Search/Build.html2
-rw-r--r--rt/share/html/Search/Elements/BuildFormatString12
-rw-r--r--rt/share/html/Search/Elements/ConditionRow3
-rw-r--r--rt/share/html/Search/Elements/PickBasics3
11 files changed, 232 insertions, 225 deletions
diff --git a/rt/share/html/Callbacks/SearchCustomerFields/Search/Elements/PickBasics/Default b/rt/share/html/Callbacks/SearchCustomerFields/Search/Elements/PickBasics/Default
deleted file mode 100644
index 369912b47..000000000
--- a/rt/share/html/Callbacks/SearchCustomerFields/Search/Elements/PickBasics/Default
+++ /dev/null
@@ -1,59 +0,0 @@
-<%init>
-push @$Conditions,
- {
- Name => 'Agentnum',
- Field => 'Agent',
- Op => {
- Type => 'component',
- Path => '/Elements/SelectBoolean',
- Arguments => { TrueVal=> '=', FalseVal => '!=' },
- },
- Value => {
- Type => 'component',
- Path => '/Elements/SelectCustomerAgent',
- },
- },
- {
- Name => 'Classnum',
- Field => 'Customer Class',
- Op => {
- Type => 'component',
- Path => '/Elements/SelectBoolean',
- Arguments => { TrueVal=> '=', FalseVal => '!=' },
- },
- Value => {
- Type => 'component',
- Path => '/Elements/SelectCustomerClass',
- },
- },
- {
- Name => 'Tagnum',
- Field => 'Tag',
- Op => {
- Type => 'component',
- Path => '/Elements/SelectBoolean',
- Arguments => { TrueVal=> '=', FalseVal => '!=' },
- },
- Value => {
- Type => 'component',
- Path => '/Elements/SelectCustomerTag',
- },
- },
- {
- Name => 'Refnum',
- Field => 'Advertising Source',
- Op => {
- Type => 'component',
- Path => '/Elements/SelectBoolean',
- Arguments => { TrueVal=> '=', FalseVal => '!=' },
- },
- Value => {
- Type => 'component',
- Path => '/Elements/SelectCustomerReferral',
- },
- },
-;
-</%init>
-<%ARGS>
-$Conditions => []
-</%ARGS>
diff --git a/rt/share/html/Elements/CustomerFields b/rt/share/html/Elements/CustomerFields
new file mode 100644
index 000000000..553a34999
--- /dev/null
+++ b/rt/share/html/Elements/CustomerFields
@@ -0,0 +1,215 @@
+<%doc>
+All accessible Freeside customer fields fields go in here. Those of
+them outside cust_main also need to go in RT::URI::freeside::Internal
+(where they should be pulled into CustomerInfo). Nothing should need
+to go in RT::Tickets_Overlay; it already resolves "Customer.foo" as
+"cust_main.foo", and "Customer.cust_bar.foo" as "JOIN cust_bar using
+(custnum) ... cust_bar.foo".
+
+About the keys:
+- 'Value' makes the field a search criterion. This also requires 'Op'.
+ See Search/Elements/PickBasics.
+- 'Display' makes it an output column, and is either the cust_main
+ field, the CustomerInfo key, or a coderef that takes the RT::Ticket
+ as an argument.
+- 'OrderBy' makes it a sort key, and must be set to an RT-SQL field
+ name to sort by.
+</%doc>
+<%once>
+return unless $RT::URI::freeside::IntegrationType eq 'Internal';
+
+my @customer_fields = ( # ordered
+ {
+ # custnum
+ Name => 'Customer',
+ Label => 'Customer',
+ Display => sub {
+ my $Ticket = shift;
+ my @return = ();
+ foreach my $c (ticket_cust_resolvers($Ticket)) {
+ push @return, \'<A HREF="', $c->HREF, \'">',
+ $c->AsString,
+ \'</A>',
+ \'<BR>';
+ }
+ pop @return;
+ @return;
+ },
+ OrderBy => 'Customer.Number',
+ },
+ {
+ #Column name (format string)
+ Name => 'Agent',
+ # Column heading/query builder name
+ Label => 'Agent',
+ # Column value (coderef, cust_main field, or CustomerInfo key)
+ Display => 'AgentName',
+ # Query builder options
+ # RT-SQL field, defaults to Name
+ QueryName => 'Customer.agentnum',
+ #QueryLabel => 'Agent' #defaults to Label
+ Op => equals_notequals,
+ Value => select_table('agent', 'agentnum', 'agent'),
+ # RT-SQL sort key (if any)
+ OrderBy => 'Customer.agentnum',
+ },
+ {
+ Name => 'CustomerClass',
+ Label => 'Customer Class',
+ Display => 'CustomerClass',
+ QueryName => 'Customer.classnum',
+ Op => equals_notequals,
+ Value => select_table('cust_class', 'classnum', 'classname'),
+ OrderBy => 'Customer.classnum',
+ },
+ {
+ Name => 'AdvertisingSource',
+ Label => 'Advertising Source',
+ Display => 'Referral',
+ QueryName => 'Customer.refnum',
+ Op => equals_notequals,
+ Value => select_table('part_referral', 'refnum', 'referral'),
+ OrderBy => 'Customer.refnum',
+ },
+ {
+ Name => 'BillingType',
+ Label => 'Billing Type',
+ Display => 'BillingType',
+ QueryName => 'Customer.payby',
+ Op => equals_notequals,
+ Value => {
+ Type => 'select',
+ Options => [ '' => '-',
+ map { $_, FS::payby->longname($_) } FS::payby->cust_payby
+ ],
+ },
+ },
+ {
+ Name => 'InvoiceEmail',
+ Label => 'Invoice Email',
+ Display => 'InvoiceEmail',
+ # query/sort needed?
+ },
+ {
+ Name => 'City',
+ Label => 'City',
+ Display => 'city',
+ OrderBy => 'Customer.city',
+ },
+ {
+ Name => 'State',
+ Label => 'State',
+ Display => 'state',
+ OrderBy => 'Customer.state',
+ },
+ {
+ Name => 'CustomerTags',
+ Label => '',
+ Display => sub {
+ my $Ticket = shift;
+ my @return = ();
+ foreach my $c (ticket_cust_resolvers($Ticket)) {
+ foreach my $t (@{ $c->CustomerInfo->{CustomerTags} }) {
+ push @return, \'<SPAN style="background-color:#',
+ $t->{'color'},
+ \';">&nbsp;',
+ $t->{'name'},
+ \'&nbsp;</SPAN>',
+ \'&nbsp;'
+ ;
+ }
+ pop @return;
+ push @return, \'<BR>';
+ }
+ pop @return;
+ @return;
+ },
+ QueryName => 'Customer.cust_tag.tagnum',
+ QueryLabel => 'Tag',
+ Op => equals_notequals,
+ Value => select_table('part_tag', 'tagnum', 'tagname'),
+ OrderBy => '',
+ },
+);
+
+#helper subs
+#Op
+sub equals_notequals {
+ return {
+ Type => 'component',
+ Path => '/Elements/SelectBoolean',
+ Arguments => { TrueVal=> '=', FalseVal=> '!=' },
+ }
+}
+
+#Value
+sub select_table {
+ my ($table, $value_col, $name_col, $hashref) = @_;
+ $hashref ||= { disabled => '' }; # common case
+ return {
+ Type => 'select',
+ Options => [
+ '' => '-',
+ map { $_->$value_col, $_->$name_col }
+ qsearch($table, $hashref)
+ ],
+ }
+}
+
+sub ticket_cust_resolvers {
+ my $Ticket = shift;
+ my @Customers = @{ $Ticket->Customers->ItemsArrayRef };
+ return map $_->TargetURI->Resolver, @Customers;
+}
+
+sub cust_info_attribute { # the simple case of $resolver->CustomerInfo->{foo}
+ my $attribute = shift;
+ sub {
+ my $Ticket = shift;
+ my @return;
+ foreach my $c (ticket_cust_resolvers($Ticket)) {
+ push @return, $c->CustomerInfo->{$attribute}, '<BR>';
+ }
+ pop @return; #trailing <BR>
+ @return;
+ };
+}
+
+</%once>
+<%init>
+return unless $RT::URI::freeside::IntegrationType eq 'Internal';
+
+my $arg = shift;
+if ( $arg eq 'Names' ) {
+ return map { $_->{Name} } @customer_fields;
+}
+elsif ( $arg eq 'ColumnMap' ) {
+ return map {
+ my $f = $_;
+
+ $f->{Name} => {
+ title => $f->{Label},
+ attribute => $f->{OrderBy} || '',
+ value => ref($f->{Display}) eq 'CODE' ?
+ $f->{Display} :
+ cust_info_attribute($f->{Display})
+ }
+ } #map
+ grep { exists $_->{Display} }
+ @customer_fields;
+}
+elsif ( $arg eq 'PickBasics' ) {
+ return map {
+ my $f = $_;
+ {
+ Name => ($f->{QueryName} || $f->{Name}),
+ Field => ($f->{QueryLabel} || $f->{Label}),
+ Op => $f->{Op},
+ Value => $f->{Value},
+ }
+ } #map
+ grep { exists $_->{Value} }
+ @customer_fields;
+}
+else { die "unknown CustomerFields mode '$arg'\n"; }
+</%init>
diff --git a/rt/share/html/Elements/RT__Ticket/ColumnMap b/rt/share/html/Elements/RT__Ticket/ColumnMap
index cd6ca1fe1..9e6466cdd 100644
--- a/rt/share/html/Elements/RT__Ticket/ColumnMap
+++ b/rt/share/html/Elements/RT__Ticket/ColumnMap
@@ -318,100 +318,11 @@ $COLUMN_MAP = {
return \$bookmark;
},
},
-
- Customer => {
- title => 'Customer', #loc
- attribute => 'Customer.Number', #title/attribute/name... what does it all mean?
- value => sub {
- my $Ticket = shift;
- my @return = ();
- foreach my $c (ticket_cust_resolvers($Ticket)) {
- push @return, \'<A HREF="', $c->HREF, \'">',
- $c->AsString,
- \'</A>',
- \'<BR>';
- }
- pop @return;
- @return;
- },
- },
- # For future reference:
- # hash key = name of the column in the format string
- # (see /Search/Elements/BuildFormatString)
- # title = displayed name in the table header
- # attribute = the field to ORDER BY when sorting on this column
- Agent => {
- title => 'Agent',
- attribute => 'Customer.Agent',
- value => sub {
- my $Ticket = shift;
- my @return = ();
- foreach my $c (ticket_cust_resolvers($Ticket)) {
- push @return, $c->AgentName, \'<BR>';
- }
- pop @return;
- @return;
- },
- },
- CustomerClass => {
- title => 'Class',
- attribute => 'Customer.Class',
- value => sub {
- my $Ticket = shift;
- my @return = ();
- foreach my $c (ticket_cust_resolvers($Ticket)) {
- push @return, $c->CustomerClass, \'<BR>';
- }
- pop @return;
- @return;
- },
- },
- CustomerTags => {
- title => '',
- attribute => '',
- value => sub {
- my $Ticket = shift;
- my @return = ();
- foreach my $c (ticket_cust_resolvers($Ticket)) {
- my @tags = sort { $a->{'name'} cmp $b->{'name'} }
- $c->CustomerTags;
- foreach my $t (@tags) {
- push @return, \'<SPAN style="background-color:#',
- $t->{'color'},
- \';">&nbsp;',
- $t->{'name'},
- \'&nbsp;</SPAN>',
- \'&nbsp;'
- ;
- }
- pop @return;
- push @return, \'<BR>';
- }
- pop @return;
- @return;
- },
- },
- AdvertisingSource => {
- title => 'Advertising Source',
- attribute => 'Customer.Referral',
- value => sub {
- my $Ticket = shift;
- my @return = ();
- foreach my $c (ticket_cust_resolvers($Ticket)) {
- push @return, $c->Referral, \'<BR>';
- }
- pop @return;
- @return;
- },
- },
+
+ #freeside
+ $m->comp('/Elements/CustomerFields', 'ColumnMap'),
};
-sub ticket_cust_resolvers {
- my $Ticket = shift;
- my @Customers = @{ $Ticket->Customers->ItemsArrayRef };
- return map $_->TargetURI->Resolver, @Customers;
-}
-
# if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular
# versions
if (RT->Config->Get('GnuPG')->{'Enable'}) {
diff --git a/rt/share/html/Elements/SelectCustomerAgent b/rt/share/html/Elements/SelectCustomerAgent
deleted file mode 100644
index 75a1fba63..000000000
--- a/rt/share/html/Elements/SelectCustomerAgent
+++ /dev/null
@@ -1,17 +0,0 @@
-% return if ($RT::URI::freeside::IntegrationType ne 'Internal');
-<select name="<%$Name%>">
-% if ($ShowNullOption) {
- <option value="">-</option>
-% }
-% for my $agent (qsearch('agent', {'disabled' => ''})) {
- <option value="<%$agent->agentnum%>" <%
- $agent->agentnum == $Default||'' ? 'selected' : ''%>
- ><%$agent->agent%></option>
-% }
-</select>
-<%init></%init>
-<%args>
-$ShowNullOption => 1
-$Name => undef
-$Default => 0
-</%args>
diff --git a/rt/share/html/Elements/SelectCustomerClass b/rt/share/html/Elements/SelectCustomerClass
deleted file mode 100644
index 1a03cba8f..000000000
--- a/rt/share/html/Elements/SelectCustomerClass
+++ /dev/null
@@ -1,17 +0,0 @@
-% return if ($RT::URI::freeside::IntegrationType ne 'Internal');
-<select name="<%$Name%>">
-% if ($ShowNullOption) {
- <option value="">-</option>
-% }
-% for my $class (qsearch('cust_class', {'disabled' => ''})) {
- <option value="<%$class->classnum%>" <%
- $class->classnum == $Default||'' ? 'selected' : ''%>
- ><%$class->classname%></option>
-% }
-</select>
-<%init></%init>
-<%args>
-$ShowNullOption => 1
-$Name => undef
-$Default => 0
-</%args>
diff --git a/rt/share/html/Elements/SelectCustomerReferral b/rt/share/html/Elements/SelectCustomerReferral
deleted file mode 100644
index 84191f82b..000000000
--- a/rt/share/html/Elements/SelectCustomerReferral
+++ /dev/null
@@ -1,17 +0,0 @@
-% return if ($RT::URI::freeside::IntegrationType ne 'Internal');
-<select name="<%$Name%>">
-% if ($ShowNullOption) {
- <option value="">-</option>
-% }
-% for my $referral (qsearch('part_referral', {'disabled' => ''})) {
- <option value="<%$referral->refnum%>" <%
- $referral->refnum == $Default||'' ? 'selected' : ''%>
- ><%$referral->referral%></option>
-% }
-</select>
-<%init></%init>
-<%args>
-$ShowNullOption => 1
-$Name => undef
-$Default => 0
-</%args>
diff --git a/rt/share/html/Elements/SelectCustomerTag b/rt/share/html/Elements/SelectCustomerTag
deleted file mode 100644
index 862766966..000000000
--- a/rt/share/html/Elements/SelectCustomerTag
+++ /dev/null
@@ -1,17 +0,0 @@
-% return if ($RT::URI::freeside::IntegrationType ne 'Internal');
-<select name="<%$Name%>">
-% if ($ShowNullOption) {
- <option value="">-</option>
-% }
-% for my $tag (qsearch('part_tag', {'disabled' => ''})) {
- <option value="<%$tag->tagnum%>" <%
- $tag->tagnum == $Default||'' ? 'selected' : ''%>
- ><%$tag->tagname%></option>
-% }
-</select>
-<%init></%init>
-<%args>
-$ShowNullOption => 1
-$Name => undef
-$Default => 0
-</%args>
diff --git a/rt/share/html/Search/Build.html b/rt/share/html/Search/Build.html
index 9507a2dbb..506384c4b 100644
--- a/rt/share/html/Search/Build.html
+++ b/rt/share/html/Search/Build.html
@@ -188,7 +188,7 @@ my @new_values = ();
# {{{ Try to find if we're adding a clause
foreach my $arg ( keys %ARGS ) {
- next unless $arg =~ m/^ValueOf(\w+|'CF.{.*?}')$/
+ next unless $arg =~ m/^ValueOf([\w\.]+|'CF.{.*?}')$/
&& ( ref $ARGS{$arg} eq "ARRAY"
? grep $_ ne '', @{ $ARGS{$arg} }
: $ARGS{$arg} ne '' );
diff --git a/rt/share/html/Search/Elements/BuildFormatString b/rt/share/html/Search/Elements/BuildFormatString
index f77c8da84..96e6a2863 100644
--- a/rt/share/html/Search/Elements/BuildFormatString
+++ b/rt/share/html/Search/Elements/BuildFormatString
@@ -69,11 +69,15 @@ $CurrentDisplayColumns => undef
# it -- and it grows per request.
# All the things we can display in the format string by default
-my @fields = qw(
+# referenced by their ColumnMap keys
+my @fields = (
+ qw(
id QueueName Subject
+ ),
+
+ $m->comp('/Elements/CustomerFields', 'Names'), #freeside
- Customer Agent CustomerClass CustomerTags AdvertisingSource
-
+ qw(
Status ExtendedStatus UpdateStatus
Type
@@ -99,7 +103,7 @@ my @fields = qw(
Bookmark
NEWLINE
-
+ )
); # loc_qw
$m->callback( CallbackOnce => 1, CallbackName => 'SetFieldsOnce', Fields => \@fields );
diff --git a/rt/share/html/Search/Elements/ConditionRow b/rt/share/html/Search/Elements/ConditionRow
index fe21f4d66..65e217639 100644
--- a/rt/share/html/Search/Elements/ConditionRow
+++ b/rt/share/html/Search/Elements/ConditionRow
@@ -82,7 +82,8 @@ $handle_block = sub {
my $res = '';
$res .= qq{<select id="$name" name="$name">};
my @options = @{ $box->{'Options'} };
- while( my $k = shift @options ) {
+ while( @options ) {
+ my $k = shift @options;
my $v = shift @options;
$res .= qq{<option value="$k">$v</option>};
}
diff --git a/rt/share/html/Search/Elements/PickBasics b/rt/share/html/Search/Elements/PickBasics
index b03fc15d5..ff30f7c11 100644
--- a/rt/share/html/Search/Elements/PickBasics
+++ b/rt/share/html/Search/Elements/PickBasics
@@ -209,6 +209,9 @@ my @lines = (
},
);
+#freeside
+push @lines, $m->comp('/Elements/CustomerFields', 'PickBasics');
+
$m->callback( Conditions => \@lines );
</%INIT>