fix broadband reporting with giant query URLs (large numbers of package defs, etc...
[freeside.git] / httemplate / search / svc_broadband-map.html
1 <& /elements/header.html, 'Broadband Search Results' &>
2   
3 <& elements/gmap.html, features => \@features, overlays => \@overlays &>
4
5 <& /elements/footer.html &>
6 <%init>
7
8 die "access denied" unless
9   $FS::CurrentUser::CurrentUser->access_right('List services');
10
11 my $conf = new FS::Conf;
12
13 $m->comp('/elements/handle_uri_query');
14
15 my @features; # geoJSON structure
16
17 # accept all the search logic from svc_broadband.cgi...
18 my %search_hash;
19 if ( $cgi->param('magic') eq 'unlinked' ) {
20   %search_hash = ( 'unlinked' => 1 );
21 } else {
22   foreach (qw( custnum agentnum svcpart cust_fields )) {
23     $search_hash{$_} = $cgi->param($_) if $cgi->param($_);
24   }
25   foreach (qw(pkgpart routernum towernum sectornum)) {
26     $search_hash{$_} = [ $cgi->param($_) ] if $cgi->param($_);
27   }
28 }
29
30 if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
31   $search_hash{'order_by'} = "ORDER BY $1";
32 }
33
34 my $sql_query = FS::svc_broadband->search(\%search_hash);
35
36 my %routerbyblock = ();
37
38 my @rows = qsearch($sql_query);
39 my %sectors;
40 my %towers;
41 my %tower_coord;
42 my %tower_bounds;
43 foreach my $svc_broadband (@rows) {
44   # don't try to show it if coords aren't set
45   next if !$svc_broadband->latitude || !$svc_broadband->longitude;
46   # coerce coordinates to numbers
47   my @coord = (
48     $svc_broadband->longitude + 0,
49     $svc_broadband->latitude + 0,
50   );
51   push @coord, $svc_broadband->altitude + 0
52     if length($svc_broadband->altitude); # it's optional
53
54   push @features,
55   {
56     id        => 'svc_broadband/'.$svc_broadband->svcnum,
57     geometry  => {
58       type        => 'Point',
59       coordinates => \@coord,
60     },
61     properties => {
62       content => include('.svc_broadband', $svc_broadband),
63     },
64   };
65   # look up tower location and draw connecting line
66   next if !$svc_broadband->sectornum;
67   my $sector = $sectors{$svc_broadband->sectornum} ||= $svc_broadband->tower_sector;
68   my $towernum = $sector->towernum;
69   my $tower = $towers{$towernum};
70
71   if (!$tower) {
72     $tower = $towers{$towernum} = $sector->tower;
73     $tower_coord{$towernum} =
74       [ $tower->longitude + 0,
75         $tower->latitude + 0,
76         ($tower->altitude || 0) + 0,
77       ];
78
79   }
80
81   if ( $tower->latitude and $tower->longitude ) {
82     push @features,
83     {
84       geometry => {
85         type        => 'LineString',
86         coordinates => [ \@coord, $tower_coord{$towernum} ],
87       },
88       properties  => {
89         style       => {
90           strokeColor  => ($tower->color || 'green'),
91           strokeWeight => 2,
92         },
93       },
94     };
95
96     # also extend tower's ROI to include this point
97     # (this is experimental; might get better results using the centroid of
98     # all connected services or something)
99     my $bounds = $tower_bounds{$towernum} ||= {
100       east => $tower->longitude,
101       west => $tower->longitude,
102       north => $tower->latitude,
103       south => $tower->latitude,
104     };
105     if ($coord[0] > $bounds->{east}) {
106       $bounds->{east} = $coord[0];
107     } elsif ($coord[0] < $bounds->{west}) {
108       $bounds->{west} = $coord[0];
109     }
110     if ($coord[1] > $bounds->{north}) {
111       $bounds->{north} = $coord[1]
112     } elsif ($coord[1] < $bounds->{south}) {
113       $bounds->{south} = $coord[1]
114     }
115
116   } # if tower has coords
117 } # foreach $svc_broadband
118
119 # if we were given a towernum or sectornum, ensure that the map includes
120 # that tower/sector, even if there are no services
121
122 foreach my $towernum ($cgi->param('towernum')) {
123   next if $towernum !~ /^\d+$/;
124   next if exists($towers{$towernum});
125   $towers{$towernum} = FS::tower->by_key($towernum);
126 }
127
128 foreach my $sectornum ($cgi->param('sectornum')) {
129   next if $sectornum !~ /^\d+$/;
130   next if exists($sectors{$sectornum});
131   $sectors{$sectornum} = FS::tower_sector->by_key($sectornum)
132     or die "bad sectornum $sectornum";
133   # and put it on the tower list also
134   my $towernum = $sectors{$sectornum}->towernum;
135   if (!exists($towers{$towernum})) {
136     $towers{$towernum} = FS::tower->by_key($towernum);
137   }
138 }
139
140 # if the tower/sector was included in the search, but has no services, set
141 # default bounds around it of 1 minute in each direction
142 my $default_bounds = 0.017;
143
144 foreach my $tower (values(%towers)) {
145   my $towernum = $tower->towernum;
146   $tower_coord{$towernum} ||= [ $tower->longitude + 0,
147                                 $tower->latitude + 0,
148                                 ($tower->altitude || 0) + 0
149                               ];
150 warn encode_json($tower_coord{$towernum});
151   my $bounds = $tower_bounds{$towernum}
152            ||= { 'north' => $tower->latitude + $default_bounds,
153                  'south' => $tower->latitude - $default_bounds,
154                  'east'  => $tower->longitude + $default_bounds,
155                  'west'  => $tower->longitude - $default_bounds,
156                };
157   # add some padding for easier reading
158   my $dx = 0.1 * ($bounds->{east} - $bounds->{west});
159   my $dy = 0.1 * ($bounds->{north} - $bounds->{south});
160   $bounds->{east} += $dx; 
161   $bounds->{west} -= $dx;
162   $bounds->{north} += $dy;
163   $bounds->{south} -= $dy;
164   push @features,
165   {
166     id        => 'tower/'.$towernum,
167     geometry  => {
168       type        => 'Point',
169       coordinates => $tower_coord{$towernum},
170     },
171     properties => {
172       style     => {
173         icon => {
174           path        => undef,
175           url         => $fsurl.'images/antenna-square-21x51.png',
176           anchor      => { x => 10, y => 4 }
177         },
178       },
179       content   => include('.tower', $tower),
180       bounds    => $tower_bounds{$towernum},
181     },
182   };
183 }
184
185 my @overlays;
186 foreach my $sector (values %sectors) {
187   if ( length($sector->image) > 0 ) {
188     my $o = {
189       url => $fsurl.'view/sector_map-png.cgi?' . $sector->sectornum
190     };
191     foreach (qw(south north west east)) {
192       $o->{$_} = $sector->get($_) + 0;
193     }
194     push @overlays, $o;
195   };
196 };
197 </%init>
198 <%def .svc_broadband>
199 % my $svc = shift;
200 % my @label = $svc->cust_svc->label;
201 <H3>
202   <a target="_blank" href="<% $fsurl %>view/svc_broadband.cgi?<% $svc->svcnum %>">
203     <% $label[0] |h %> #<% $svc->svcnum %> | <% $label[1] %>
204   </a>
205 </H3>
206 % my $cust_main = $svc->cust_main;
207 <a target="_blank" href="<% $fsurl %>view/cust_main.cgi?<% $cust_main->custnum %>">
208 <& /elements/small_custview.html, {
209   cust_main => $svc->cust_main,
210   #url => $fsurl.'view/cust_main.cgi',
211 } &>
212 </a>
213 </%def>
214 <%def .tower>
215 % my $tower = shift;
216 % my $can_edit = $FS::CurrentUser::CurrentUser->access_right('Configuration');
217 <H3>
218 % if ( $can_edit ) {
219   <a target="_blank" href="<% $fsurl %>edit/tower.html?<% $tower->towernum %>">
220 % }
221 Tower #<% $tower->towernum %> | <% $tower->towername %>
222 % if ( $can_edit ) {
223   </a>
224 % }
225 </H3>
226 </%def>