RT# 73422 Fix report Customer Contacts
[freeside.git] / httemplate / search / contact.html
1 <& elements/search.html,
2   title         => emt('Contacts'),
3   name_singular => 'contact',
4   query         => {
5     select    => join(', ', @select),
6     table     => 'contact',
7     addl_from => $addl_from,
8     hashref   => {}, #\%hash,
9     extra_sql => "WHERE $extra_sql",
10     order_by  => "ORDER BY contact_last,contact_first,contact_email_emailaddress"
11   },
12   count_query => "
13     SELECT COUNT(*)
14     FROM contact
15     $addl_from
16     WHERE $extra_sql
17   ",
18   header    => \@header,
19   fields    => \@fields,
20   links     => \@links,
21   html_init => $send_email_link,
22 #  agent_virt    => 1, # Not supported unless table is cust_main/prospect_main
23 &>
24 <%init>
25
26 die "access denied"
27   unless $FS::CurrentUser::CurrentUser->access_right('List contacts');
28
29 my $DEBUG = 0;
30
31 # Catch classnum values from multi-select box
32 # A classnum of 0 indicates to include rows where classnum IS NULL
33 $CGI::LIST_CONTEXT_WARN = 0;
34 my @classnum      = grep{ /^\d+$/ && $_ > 0 } $cgi->param('classnum');
35 my $classnum_null = grep{ $_ eq 0           } $cgi->param('classnum');
36
37 # Catch destination values from dest multi-checkbox, default to message
38 # irrelevant to prospect contacts
39 my @dest = grep{ /^(message|invoice)$/ } $cgi->param('dest');
40 @dest = ('message') unless @dest;
41
42
43 # Cache the contact_class table
44 my %classname =
45   map {$_->classnum => $_->classname}
46   qsearch(contact_class => {disabled => ''});
47
48 # This data structure is used to generate the sql query parameters
49 my %colmap = (
50   # These are included regardless of which tables we're viewing
51   common => {
52     cols => {
53       contact => [qw/first last title contactnum/],
54       contact_email => [qw/emailaddress/],
55     },
56     joinsql => "
57       LEFT JOIN contact_email
58         ON (contact.contactnum = contact_email.contactnum)
59     ",
60   },
61
62   # These are included if we're viewing customer records
63   customer => {
64     cols => {
65       cust_main => [qw/first last company/],
66       cust_contact => [qw/
67         custnum classnum invoice_dest message_dest selfservice_access comment
68       /],
69     },
70     joinsql => "
71       LEFT JOIN cust_contact
72         ON (contact.contactnum = cust_contact.contactnum)
73       LEFT JOIN cust_main
74         ON (cust_contact.custnum = cust_main.custnum)
75     ",
76   },
77
78   # These are included if we're viewing prospect records
79   prospect => {
80     cols => {
81       prospect_main => [qw/company/],
82       prospect_contact => [qw/prospectnum classnum comment/],
83     },
84     joinsql => "
85       LEFT JOIN prospect_contact
86         ON (contact.contactnum = prospect_contact.contactnum)
87       LEFT JOIN prospect_main
88         ON (prospect_contact.prospectnum = prospect_main.prospectnum)
89     ",
90   },
91 );
92
93 my @select;
94 my $addl_from;
95 my $extra_sql;
96 my $hashref;
97 my $link = $cgi->param('link'); # cust_main, prospect_main or both
98
99 my @rectypes = ('common');
100 push @rectypes,'customer' if $link eq 'cust_main'     || $link eq 'both';
101 push @rectypes,'prospect' if $link eq 'prospect_main' || $link eq 'both';
102
103 # Build @select and $addl_from
104 for my $key (@rectypes) {
105   $addl_from .= $colmap{$key}->{joinsql};
106   my $cols = $colmap{$key}->{cols};
107   for my $tbl (keys %{$cols}) {
108     push @select, map{ "$tbl.$_ AS ${tbl}_$_" } @{$cols->{$tbl}};
109   }
110 }
111
112 # Filter for custnum/prospectnum
113 $extra_sql .= ' (';
114 $extra_sql .= "cust_contact.custnum IS NOT NULL"
115   if $link eq 'cust_main' || $link eq 'both';
116 $extra_sql .= " OR " if $link eq 'both';
117 $extra_sql .= "prospect_contact.prospectnum IS NOT NULL"
118   if $link eq 'prospect_main' || $link eq 'both';
119 $extra_sql .= ') ';
120
121 # Filter for Contact Type
122 if (@classnum || $classnum_null) {
123   my @stm;
124
125   push @stm, 'cust_contact.classnum IN ('.join(',',@classnum).')'
126     if @classnum && ($link eq 'cust_main' || $link eq 'both');
127
128   push @stm, 'prospect_contact.classnum IN ('.join(',',@classnum).')'
129     if @classnum && ($link eq 'prospect_main' || $link eq 'both');
130
131   push @stm, 'cust_contact.classnum IS NULL'
132     if $classnum_null && ($link eq 'cust_main' || $link eq 'both');
133
134   push @stm, 'prospect_contact.classnum IS NULL'
135     if $classnum_null && ($link eq 'prospect_main' || $link eq 'both');
136
137   $extra_sql .= "\nAND (" . join(' OR ',@stm) . ') ';
138 }
139
140 # Filter for destination
141 if (@dest && ($link eq 'cust_main' || $link eq 'both')) {
142   my @stm;
143   push @stm, "cust_contact.${_}_dest IS NOT NULL" for @dest;
144   push @stm, "prospect_contact.prospectnum IS NOT NULL" if $link eq 'both';
145   $extra_sql .= "\nAND (".join(' OR ',@stm).') ';
146 }
147
148 if ($DEBUG) {
149   print "<pre>\n";
150   print "select \n";
151   print join ",\n",@select;
152   print "\n";
153   print "from contact \n";
154   print "$addl_from\n";
155   print "WHERE \n $extra_sql\n";
156   print "</pre>\n";
157 }
158
159 # Prepare to display phone numbers
160 my %phonetype = (qw/1 Work 2 Home 3 Mobile 4 Fax/);
161 my %phoneid   = (qw/Work 1 Home 2 Mobile 3 Fax 4/);
162 my $get_phone_sub = sub {
163   my $type = shift;
164   return sub {
165     my $rec = shift;
166     my @p = qsearch('contact_phone', {
167       contactnum => $rec->contact_contactnum,
168       phonetypenum => $phoneid{$type}
169     });
170     @p ? (join ', ',map{$_->phonenum} @p) : undef;
171   };
172 };
173
174 # Cache contact types
175 my %classname =
176   map {$_->classnum => $_->classname}
177   qsearch(contact_class => {disabled => ''});
178
179 # And now for something completly different:
180 my @report = (
181   { label => 'First', field => sub { shift->contact_first }},
182   { label => 'Last', field => sub { shift->contact_last }},
183   { label => 'Title', field => sub { shift->contact_title }},
184   { label => 'E-Mail', field => sub { shift->contact_email_emailaddress }},
185   { label => 'Work Phone', field => $get_phone_sub->('Work') },
186   { label => 'Mobile Phone', field => $get_phone_sub->('Mobile') },
187   { label => 'Home Phone', field => $get_phone_sub->('Home') },
188   { label => 'Type',
189     field => sub {
190       my $rec = shift;
191       if ($rec->cust_contact_custnum) {
192         return $rec->cust_contact_classnum
193                ? $classname{$rec->cust_contact_classnum}
194                : undef;
195       } else {
196         return $rec->prospect_contact_classnum
197                ? $classname{$rec->prospect_contact_classnum}
198                : undef;
199       }
200   }},
201   { label => 'Send Invoices',
202     field => sub {
203       my $rec = shift;
204       return 'N/A' if $rec->prospect_contact_prospectnum;
205       $rec->cust_contact_invoice_dest ? 'Y' : 'N';
206     }},
207   { label => 'Send Messages',
208     field => sub {
209       my $rec = shift;
210       return 'N/A' if $rec->prospect_contact_prospectnum;
211       $rec->cust_contact_message_dest ? 'Y' : 'N';
212     }},
213   { label => 'Customer',
214     link  => sub {
215       my $rec = shift;
216       $rec->prospect_contact_prospectnum
217       ? ["${p}view/prospect_main.html?", 'prospect_contact_prospectnum' ]
218       : ["${p}view/cust_main.cgi?", 'cust_contact_custnum' ];
219     },
220     field => sub {
221       my $rec = shift;
222       if ($rec->prospect_contact_prospectnum) {
223         return $rec->contact_company
224           || $rec->contact_last.' '.$rec->contact_first;
225       }
226       $rec->cust_main_company || $rec->cust_main_last.' '.$rec->cust_main_first;
227     }},
228   { label => 'Self-service',
229     field => sub {
230       my $rec = shift;
231       return 'N/A' if $rec->prospect_contact_prospectnum;
232       $rec->cust_contact_selfservice_access ? 'Y' : 'N';
233     }},
234   { label => 'Comment',
235     field => sub {
236       my $rec = shift;
237       $rec->prospect_contact_prospectnum
238       ? $rec->prospect_contact_comment
239       : $rec->cust_contact_comment;
240     }},
241 );
242
243 my (@header, @fields, @links);
244 for my $col (@report) {
245   push @header, emt($col->{label});
246   push @fields, $col->{field};
247   push @links, ($col->{link} || "");
248 }
249
250 my $classnum_url_part;
251 if (@classnum) {
252   $classnum_url_part = join '', map{ "&classnums=$_" } @classnum, @dest;
253   $classnum_url_part .= '&classnums=0' if $classnum_null;
254 }
255
256 # E-mail pipeline doesn't support mixing prospects and customers in one go
257 my $send_email_link = undef;
258 if ($link eq 'cust_main') {
259   $send_email_link =
260     "<a href=\"${fsurl}misc/email-customers.html?".
261       'table=cust_main'.
262       '&POST=on'.
263       '&all_pkg_classnums=0'.
264       '&all_tags=0'.
265       '&any_pkg_status=0'.
266       '&refnum=1'.
267       '&with_email=on'.
268       $classnum_url_part.
269     "\">Email a notice to these customers</a>";
270 }
271
272 </%init>