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
19 return unless $RT::URI::freeside::IntegrationType eq 'Internal';
21 my @customer_fields = ( # ordered
29 foreach my $c (ticket_cust_resolvers($Ticket)) {
30 push @return, \'<A HREF="', $c->HREF, \'">',
38 OrderBy => 'Customer.Number',
41 #Column name (format string)
43 # Column heading/query builder name
45 # Column value (coderef, cust_main field, or CustomerInfo key)
46 Display => 'AgentName',
47 # Query builder options
48 # RT-SQL field, defaults to Name
49 QueryName => 'Customer.agentnum',
50 #QueryLabel => 'Agent' #defaults to Label
51 Op => equals_notequals,
52 Value => select_table('agent', 'agentnum', 'agent'),
53 # RT-SQL sort key (if any)
54 OrderBy => 'Customer.agentnum',
57 Name => 'CustomerClass',
58 Label => 'Customer Class',
59 Display => 'CustomerClass',
60 QueryName => 'Customer.classnum',
61 Op => equals_notequals,
62 Value => select_table('cust_class', 'classnum', 'classname'),
63 OrderBy => 'Customer.classnum',
66 Name => 'AdvertisingSource',
67 Label => 'Advertising Source',
68 Display => 'Referral',
69 QueryName => 'Customer.refnum',
70 Op => equals_notequals,
71 Value => select_table('part_referral', 'refnum', 'referral'),
72 OrderBy => 'Customer.refnum',
75 Name => 'BillingType',
76 Label => 'Billing Type',
77 Display => 'BillingType',
78 QueryName => 'Customer.payby',
79 Op => equals_notequals,
82 Options => [ '' => '-',
83 map { $_, FS::payby->longname($_) } FS::payby->cust_payby
88 Name => 'InvoiceEmail',
89 Label => 'Invoice Email',
90 Display => 'InvoiceEmail',
97 OrderBy => 'Customer.city',
103 OrderBy => 'Customer.state',
106 Name => 'CustomerTags',
111 foreach my $c (ticket_cust_resolvers($Ticket)) {
112 foreach my $t (@{ $c->CustomerInfo->{CustomerTags} }) {
113 push @return, \'<SPAN style="background-color:#',
122 push @return, \'<BR>';
127 QueryName => 'Customer.cust_tag.tagnum',
129 Op => equals_notequals,
130 Value => select_table('part_tag', 'tagnum', 'tagname'),
137 sub equals_notequals {
140 Path => '/Elements/SelectBoolean',
141 Arguments => { TrueVal=> '=', FalseVal=> '!=' },
147 my ($table, $value_col, $name_col, $hashref) = @_;
148 $hashref ||= { disabled => '' }; # common case
153 map { $_->$value_col, $_->$name_col }
154 qsearch($table, $hashref)
159 sub ticket_cust_resolvers {
161 my @Customers = @{ $Ticket->Customers->ItemsArrayRef };
162 return map $_->TargetURI->Resolver, @Customers;
165 sub cust_info_attribute { # the simple case of $resolver->CustomerInfo->{foo}
166 my $attribute = shift;
170 foreach my $c (ticket_cust_resolvers($Ticket)) {
171 push @return, $c->CustomerInfo->{$attribute}, '<BR>';
173 pop @return; #trailing <BR>
180 return unless $RT::URI::freeside::IntegrationType eq 'Internal';
183 if ( $arg eq 'Names' ) {
184 return map { $_->{Name} } @customer_fields;
186 elsif ( $arg eq 'ColumnMap' ) {
191 title => $f->{Label},
192 attribute => $f->{OrderBy} || '',
193 value => ref($f->{Display}) eq 'CODE' ?
195 cust_info_attribute($f->{Display})
198 grep { exists $_->{Display} }
201 elsif ( $arg eq 'PickBasics' ) {
205 Name => ($f->{QueryName} || $f->{Name}),
206 Field => ($f->{QueryLabel} || $f->{Label}),
208 Value => $f->{Value},
211 grep { exists $_->{Value} }
214 else { die "unknown CustomerFields mode '$arg'\n"; }