2 All accessible Freeside customer fields fields go in here. Those of
3 them outside cust_main also need to go in RT::URI::freeside::Internal
4 (where they should be pulled into CustomerInfo). Nothing should need
5 to go in RT::Tickets_Overlay; it already resolves "Customer.foo" as
6 "cust_main.foo", and "Customer.cust_bar.foo" as "JOIN cust_bar using
7 (custnum) ... cust_bar.foo".
10 - 'Value' makes the field a search criterion. This also requires 'Op'.
11 See Search/Elements/PickBasics.
12 - 'Display' makes it an output column, and is either the cust_main
13 field, the CustomerInfo key, or a coderef that takes the RT::Ticket
15 - 'OrderBy' makes it a sort key, and must be set to an RT-SQL field
20 my @customer_fields = ( # ordered
28 foreach my $c (ticket_cust_resolvers($Ticket)) {
29 push @return, \'<A HREF="', $c->HREF, \'">',
37 OrderBy => 'Customer.Number',
40 #Column name (format string)
42 # Column heading/query builder name
44 # Column value (coderef, cust_main field, or CustomerInfo key)
45 Display => 'AgentName',
46 # Query builder options
47 # RT-SQL field, defaults to Name
48 QueryName => 'Customer.agentnum',
49 #QueryLabel => 'Agent' #defaults to Label
50 Op => equals_notequals,
51 Value => select_table('agent', 'agentnum', 'agent'),
52 # RT-SQL sort key (if any)
53 OrderBy => 'Customer.agentnum',
56 Name => 'CustomerClass',
57 Label => 'Customer Class',
58 Display => 'CustomerClass',
59 QueryName => 'Customer.classnum',
60 Op => equals_notequals,
61 Value => select_table('cust_class', 'classnum', 'classname'),
62 OrderBy => 'Customer.classnum',
65 Name => 'AdvertisingSource',
66 Label => 'Advertising Source',
67 Display => 'Referral',
68 QueryName => 'Customer.refnum',
69 Op => equals_notequals,
70 Value => select_table('part_referral', 'refnum', 'referral'),
71 OrderBy => 'Customer.refnum',
74 Name => 'BillingType',
75 Label => 'Billing Type',
76 Display => 'BillingType',
77 QueryName => 'Customer.payby',
78 Op => equals_notequals,
81 Options => [ '' => '-',
82 map { $_, FS::payby->longname($_) } FS::payby->cust_payby
87 Name => 'InvoiceEmail',
88 Label => 'Invoice Email',
89 Display => 'InvoiceEmail',
96 OrderBy => 'Customer.city',
102 OrderBy => 'Customer.state',
105 Name => 'CustomerTags',
110 foreach my $c (ticket_cust_resolvers($Ticket)) {
111 foreach my $t (@{ $c->CustomerInfo->{CustomerTags} }) {
112 push @return, \'<SPAN style="background-color:#',
121 push @return, \'<BR>';
126 QueryName => 'Customer.cust_tag.tagnum',
128 Op => equals_notequals,
129 Value => select_table('part_tag', 'tagnum', 'tagname'),
136 sub equals_notequals {
139 Path => '/Elements/SelectBoolean',
140 Arguments => { TrueVal=> '=', FalseVal=> '!=' },
146 my ($table, $value_col, $name_col, $hashref) = @_;
147 $hashref ||= { disabled => '' }; # common case
152 map { $_->$value_col, $_->$name_col }
153 qsearch($table, $hashref)
158 sub ticket_cust_resolvers {
160 my @Customers = map { $_->TargetURI->Resolver->CustomerResolver }
161 @{ $Ticket->Customers->ItemsArrayRef };
162 # this can contain cust_svc links, careful
164 my %seen = map { $_->URI => $_ } @Customers;
168 sub cust_info_attribute { # the simple case of $resolver->CustomerInfo->{foo}
169 my $attribute = shift;
173 foreach my $c (ticket_cust_resolvers($Ticket)) {
174 push @return, $c->CustomerInfo->{$attribute}, '<BR>';
176 pop @return; #trailing <BR>
185 if ( $arg eq 'Names' ) {
186 return map { $_->{Name} } @customer_fields;
188 elsif ( $arg eq 'ColumnMap' ) {
193 title => $f->{Label},
194 attribute => $f->{OrderBy} || '',
195 value => ref($f->{Display}) eq 'CODE' ?
197 cust_info_attribute($f->{Display})
200 grep { exists $_->{Display} }
203 elsif ( $arg eq 'Criteria' ) {
206 # argument to Search/Elements/ConditionRow
209 Name => ($f->{QueryName} || $f->{Name}),
210 Field => ($f->{QueryLabel} || $f->{Label}),
212 Value => $f->{Value},
215 grep { exists $_->{Condition} || exists $_->{Value} }
218 else { die "unknown CustomerFields mode '$arg'\n"; }