Optimize "Customer has a referring customer" condition, RT#74452
[freeside.git] / httemplate / elements / dashboard-toplist.html
1 % if ( $conf->exists('dashboard-toplist') ) {
2
3   <& /elements/table-grid.html &>
4
5 % my $bgcolor1 = '#eeeeee';
6 %     my $bgcolor2 = '#ffffff';
7 %     my $bgcolor = $bgcolor2;
8
9 % foreach my $line ( $conf->config('dashboard-toplist') ) {
10 %
11 %   if ( $bgcolor eq $bgcolor1 ) {
12 %     $bgcolor = $bgcolor2;
13 %   } else {
14 %     $bgcolor = $bgcolor1;
15 %   }
16
17 %   if ( $line =~ /^\s*cust_main:\s*(\d+)\s*$/ ) { #customer line
18 %     my $custnum = $1;
19 %     my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
20 %     if ( $cust_main ) {
21      
22         <TR>
23           <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
24             <A HREF="view/cust_main.cgi?<% $custnum %>"><% $cust_main->name |h %></A>
25           </TD>
26           <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
27             <& /elements/mcp_lint.html, 'cust_main'=>$cust_main &>
28           </TD>
29           <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
30             <FONT SIZE="-1">
31             <A HREF="<% FS::TicketSystem->href_new_ticket($cust_main) %>"><% mt('(new ticket)') |h %></A>
32             </FONT>
33           </TD>
34
35 %         foreach my $priority ( @custom_priorities ) {
36             <TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
37 %           my $num = $num_tickets_by_priority{$priority}->{$custnum};
38 %           if ( $num ) {
39               <A HREF="<%
40                    FS::TicketSystem->href_customer_tickets($custnum,$priority)
41                    %>"><% $num %></A>
42 %             if ( $priority &&
43 %                 exists($num_tickets_by_priority{''}{$custnum}) ) {
44 %                   # decrement the customer's total by the number in 
45 %                   # this priority bin
46 %                   $num_tickets_by_priority{''}{$custnum} -= $num;
47 %             }
48 %           }
49           </TD>
50 %         }
51         </TR>
52
53 %     } else { 
54
55         <TR>
56           <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
57             <% mt("Unknown customer number [_1]", $custnum) |h %> 
58           </TD>
59         </TR>
60
61 %     }
62 %
63 %   } elsif ( $line =~ /^\-\-+$/ ) { #divider
64 %     
65       <TR>
66         <TH CLASS="grid" COLSPAN="<% scalar(@custom_priorities) + 4 %>"></TH>
67       </TR>
68
69 %     next;
70 %     
71 %   } elsif ( $line =~ /^\s*$/ ) {
72
73       <TR>
74         <TD CLASS="grid" COLSPAN="<% scalar(@custom_priorities) + 4 %>" BGCOLOR="<% $bgcolor %>">&nbsp;</TD>
75       </TR>
76
77 %   } elsif ( $line =~ /^\S/ ) { #label line
78
79       <TR>
80         <TH CLASS="grid" BGCOLOR="#cccccc"><% $line %></TH>
81         <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Lint') |h %></TH>
82         <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
83 %       foreach my $priority ( @custom_priorities ) {
84           <TH CLASS="grid" BGCOLOR="#cccccc">
85             <% $priority || '<i>(none)</i>'%>
86           </TH>
87 %       }
88       </TR>
89
90 %   } else { #regular line
91
92       <TR>
93         <TD CLASS="grid"  COLSPAN="<% scalar(@custom_priorities) + 4 %>" BGCOLOR="<% $bgcolor %>"><% $line %></TD>
94       </TR>
95
96 %   }
97
98 %    
99 % } 
100
101   </TABLE>
102   <BR>
103
104 % }
105 <%init>
106
107 my $conf = new FS::Conf;
108
109 #false laziness w/httemplate/search/cust_main.cgi... care if 
110 # custom_priority_field becomes anything but a local hack...
111
112 my @custom_priorities = ();
113 my $custom_priority_field = $conf->config('ticket_system-custom_priority_field');
114 if ( $custom_priority_field 
115      && @{[ $conf->config('ticket_system-custom_priority_field-values') ]} ) {
116   @custom_priorities =
117     $conf->config('ticket_system-custom_priority_field-values');
118 }
119 push @custom_priorities, '';
120
121 my %num_tickets_by_priority = map { $_ => {} } @custom_priorities;
122 # "optimization" (i.e. "terrible hack") to avoid constructing 
123 # (@custom_priorities) x (cust_main) queries with a bazillion 
124 # joins each just to count tickets
125 if ( $FS::TicketSystem::system eq 'RT_Internal' 
126   and $conf->config('dashboard-toplist') )
127 {
128   my $text = (driver_name =~ /^Pg/) ? 'text' : 'char';
129   # The RT API does not play nicely with aggregate queries,
130   # so we're going to go around it.
131   my $sql;
132   # optimization to keep this from taking a million years
133   my $cust_tickets =
134   "SELECT custnum, Tickets.Id, Tickets.Queue
135   FROM cust_main
136   JOIN Links ON (
137     Links.Target = 'freeside://freeside/cust_main/' || CAST(cust_main.custnum AS $text)
138     AND Links.Base LIKE '%rt://%/ticket/%'
139     AND Links.Type = 'MemberOf'
140   ) JOIN Tickets ON (Links.LocalBase = Tickets.Id)
141   UNION
142   SELECT custnum, Tickets.Id, Tickets.Queue
143   FROM cust_pkg JOIN cust_svc USING (pkgnum)
144   JOIN Links ON (
145     Links.Target = 'freeside://freeside/cust_svc/' || CAST(cust_svc.svcnum AS $text)
146     AND Links.Base LIKE '%rt://%/ticket/%'
147     AND Links.Type = 'MemberOf'
148   ) JOIN Tickets ON (Links.LocalBase = Tickets.Id)
149   ";
150
151   if ( $custom_priority_field )  {
152     $sql = 
153     "SELECT cust_tickets.custnum AS custnum,
154             ObjectCustomFieldValues.Content as priority,
155             COUNT(DISTINCT cust_tickets.Id) AS num_tickets
156      FROM ($cust_tickets) AS cust_tickets
157         LEFT JOIN ObjectCustomFields ON (
158           ObjectCustomFields.ObjectId = '0' OR 
159           ObjectCustomFields.ObjectId = cust_tickets.Queue
160         )
161         LEFT JOIN CustomFields ON (
162           ObjectCustomFields.CustomField = CustomFields.Id AND
163           CustomFields.Name = '$custom_priority_field'
164         )
165         LEFT JOIN ObjectCustomFieldValues ON (
166           ObjectCustomFieldValues.CustomField = CustomFields.Id AND
167           ObjectCustomFieldValues.ObjectType = 'RT::Ticket' AND
168           ObjectCustomFieldValues.Disabled = '0' AND
169           ObjectCustomFieldValues.ObjectId = cust_tickets.Id
170         )
171       GROUP BY cust_tickets.custnum, ObjectCustomFieldValues.Content";
172   } else { # no custom_priority_field
173     $sql =
174     "SELECT cust_tickets.custnum,
175             '' as priority,
176             COUNT(DISTINCT cust_tickets.Id) AS num_tickets
177      FROM ($cust_tickets) AS cust_tickets
178       GROUP BY cust_tickets.custnum";
179   }
180   my $sth = dbh->prepare($sql) or die dbh->errstr;
181   $sth->execute or die $sth->errstr;
182   while ( my $row = $sth->fetchrow_hashref ) {
183     $num_tickets_by_priority{ $row->{priority} }->{ $row->{custnum} } =
184       $row->{num_tickets};
185   }
186 }
187 </%init>