add latitude/longitude to prospects, customers and package locations, RT#15539
authorivan <ivan>
Tue, 13 Dec 2011 05:10:23 +0000 (05:10 +0000)
committerivan <ivan>
Tue, 13 Dec 2011 05:10:23 +0000 (05:10 +0000)
27 files changed:
FS/FS/Mason.pm
FS/FS/Record.pm
FS/FS/Upgrade.pm
FS/FS/cust_location.pm
FS/FS/cust_main.pm
FS/FS/geocode_Mixin.pm
FS/FS/part_svc.pm
FS/FS/svc_broadband.pm
httemplate/docs/credits.html
httemplate/docs/license.html
httemplate/edit/cust_main.cgi
httemplate/edit/process/prospect_main.html
httemplate/edit/prospect_main.html
httemplate/elements/city.html
httemplate/elements/coord-links.html [new file with mode: 0644]
httemplate/elements/location.html
httemplate/elements/popup_link.html
httemplate/elements/tr-coords.html [new file with mode: 0644]
httemplate/elements/tr-select-cust_location.html
httemplate/view/cust_main/contacts.html
httemplate/view/cust_main/packages.html
httemplate/view/cust_main/packages/location.html
httemplate/view/cust_main/packages/section.html
httemplate/view/kml.cgi [new file with mode: 0644]
httemplate/view/map.html [new file with mode: 0644]
httemplate/view/prospect_main.html
httemplate/view/svc_broadband.cgi

index 0cb2a0b..773261f 100644 (file)
@@ -114,6 +114,8 @@ if ( -e $addl_handler_use_file ) {
                                         #selectlayers.html
   use Locale::Country;
   use Business::US::USPS::WebTools::AddressStandardization;
+  use HTML::GoogleMaps;
+  use Geo::GoogleEarth::Pluggable;
   use LWP::UserAgent;
   use Storable qw( nfreeze thaw );
   use FS;
index 514df49..126b0cb 100644 (file)
@@ -3,7 +3,7 @@ package FS::Record;
 use strict;
 use vars qw( $AUTOLOAD @ISA @EXPORT_OK $DEBUG
              %virtual_fields_cache
-             $conf $conf_encryption $money_char
+             $conf $conf_encryption $money_char $lat_lower $lon_upper
              $me
              $nowarn_identical $nowarn_classload
              $no_update_diff $no_check_foreign
@@ -56,18 +56,25 @@ my $rsa_decrypt;
 $conf = '';
 $conf_encryption = '';
 FS::UID->install_callback( sub {
+
   eval "use FS::Conf;";
   die $@ if $@;
   $conf = FS::Conf->new; 
   $conf_encryption = $conf->exists('encryption');
   $money_char = $conf->config('money_char') || '$';
+  my $nw_coords = $conf->exists('geocode-require_nw_coordinates');
+  $lat_lower = $nw_coords ? 1 : -90;
+  $lon_upper = $nw_coords ? -1 : 180;
+
   $File::CounterFile::DEFAULT_DIR = $conf->base_dir . "/counters.". datasrc;
+
   if ( driver_name eq 'Pg' ) {
     eval "use DBD::Pg ':pg_types'";
     die $@ if $@;
   } else {
     eval "sub PG_BYTEA { die 'guru meditation #9: calling PG_BYTEA when not running Pg?'; }";
   }
+
 } );
 
 =head1 NAME
@@ -2511,11 +2518,17 @@ for lower and upper bounds, respectively.
 =cut
 
 sub ut_coord {
-
   my ($self, $field) = (shift, shift);
 
-  my $lower = shift if scalar(@_);
-  my $upper = shift if scalar(@_);
+  my($lower, $upper);
+  if ( $field =~ /latitude/ ) {
+    $lower = $lat_lower;
+    $upper = 90;
+  } elsif ( $field =~ /longitude/ ) {
+    $lower = -180;
+    $upper = $lon_upper;
+  }
+
   my $coord = $self->getfield($field);
   my $neg = $coord =~ s/^(-)//;
 
@@ -2563,7 +2576,7 @@ sub ut_coordn {
 
   my ($self, $field) = (shift, shift);
 
-  if ($self->getfield($field) =~ /^$/) {
+  if ($self->getfield($field) =~ /^\s*$/) {
     return '';
   } else {
     return $self->ut_coord($field, @_);
index eac8333..3134b8c 100644 (file)
@@ -47,6 +47,9 @@ sub upgrade_config {
     if $conf->exists('payment_receipt_email')
     || $conf->config('payment_receipt_msgnum');
 
+  $conf->touch('geocode-require_nw_coordinates')
+    if $conf->exists('svc_broadband-require-nw-coordinates');
+
   upgrade_overlimit_groups($conf);
   map { upgrade_overlimit_groups($conf,$_->agentnum) } qsearch('agent', {});
   
index 7ffa5ed..a3d5bcb 100644 (file)
@@ -135,6 +135,9 @@ sub check {
     || $self->ut_textn('state')
     || $self->ut_country('country')
     || $self->ut_zip('zip', $self->country)
+    || $self->ut_coordn('latitude')
+    || $self->ut_coordn('longitude')
+    || $self->ut_enum('coord_auto', [ '', 'Y' ])
     || $self->ut_alphan('location_type')
     || $self->ut_textn('location_number')
     || $self->ut_enum('location_kind', [ '', 'R', 'B' ] )
@@ -142,6 +145,9 @@ sub check {
   ;
   return $error if $error;
 
+  $self->set_coord
+    unless $self->latitude && $self->longitude;
+
   return "No prospect or customer!" unless $self->prospectnum || $self->custnum;
   return "Prospect and customer!"       if $self->prospectnum && $self->custnum;
 
index 945b4f4..f49eb69 100644 (file)
@@ -1481,6 +1481,29 @@ sub replace {
       && length($self->get($pre.'zip')) >= 10;
   }
 
+  for my $pre ( grep $old->get($_.'coord_auto'), ( '', 'ship_' ) ) {
+
+    $self->set($pre.'coord_auto', '') && next
+      if $self->get($pre.'latitude') && $self->get($pre.'longitude')
+      && (    $self->get($pre.'latitude')  != $old->get($pre.'latitude')
+           || $self->get($pre.'longitude') != $old->get($pre.'longitude')
+         );
+
+    $self->set_coord($pre)
+      if $old->get($pre.'address1') ne $self->get($pre.'address1')
+      || $old->get($pre.'city')     ne $self->get($pre.'city')
+      || $old->get($pre.'state')    ne $self->get($pre.'state')
+      || $old->get($pre.'country')  ne $self->get($pre.'country');
+
+  }
+
+  $self->set_coord
+    if ! $self->coord_auto && ! $self->latitude && ! $self->longitude;
+
+  $self->set_coord('ship_')
+    if $self->has_ship_address && ! $self->ship_coord_auto
+    && ! $self->ship_latitude && ! $self->ship_longitude;
+
   local($ignore_expired_card) = 1
     if $old->payby  =~ /^(CARD|DCRD)$/
     && $self->payby =~ /^(CARD|DCRD)$/
@@ -1696,6 +1719,9 @@ sub check {
     || $self->ut_textn('county')
     || $self->ut_textn('state')
     || $self->ut_country('country')
+    || $self->ut_coordn('latitude')
+    || $self->ut_coordn('longitude')
+    || $self->ut_enum('coord_auto', [ '', 'Y' ])
     || $self->ut_anything('comments')
     || $self->ut_numbern('referral_custnum')
     || $self->ut_textn('stateid')
@@ -1710,6 +1736,9 @@ sub check {
     || $self->ut_enum('locale', [ '', FS::Locales->locales ])
   ;
 
+  $self->set_coord
+    unless $import || ($self->latitude && $self->longitude);
+
   #barf.  need message catalogs.  i18n.  etc.
   $error .= "Please select an advertising source."
     if $error =~ /^Illegal or empty \(numeric\) refnum: /;
@@ -1807,9 +1836,15 @@ sub check {
       || $self->ut_textn('ship_county')
       || $self->ut_textn('ship_state')
       || $self->ut_country('ship_country')
+      || $self->ut_coordn('ship_latitude')
+      || $self->ut_coordn('ship_longitude')
+      || $self->ut_enum('ship_coord_auto', [ '', 'Y' ] )
     ;
     return $error if $error;
 
+    $self->set_coord('ship_')
+      unless $import || ($self->ship_latitude && $self->ship_longitude);
+
     #false laziness with above
     unless ( qsearchs('cust_main_county', {
       'country' => $self->ship_country,
@@ -2079,6 +2114,7 @@ Returns a list of fields which have ship_ duplicates.
 sub addr_fields {
   qw( last first company
       address1 address2 city county state zip country
+      latitude longitude
       daytime night fax mobile
     );
 }
@@ -2500,8 +2536,9 @@ sub batch_card {
       'custnum'  => $self->custnum,
   } );
 
-  foreach (qw( address1 address2 city state zip country payby payinfo paydate
-               payname )) {
+  foreach (qw( address1 address2 city state zip country latitude longitude
+               payby payinfo paydate payname ))
+  {
     $options{$_} = '' unless exists($options{$_});
   }
 
index c1b9f86..9ac8e7a 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use vars qw( $DEBUG $me );
 use Carp;
 use Locale::Country;
+use Geo::Coder::Googlev3; #compile time for now, until others are supported
 use FS::Record qw( qsearchs qsearch );
 use FS::Conf;
 use FS::cust_pkg;
@@ -131,6 +132,36 @@ sub location_label {
   $line;
 }
 
+=item set_coord
+
+=cut
+
+sub set_coord {
+  my $self = shift;
+  my $pre = scalar(@_) ? shift : '';
+
+  #my $module = FS::Conf->new->config('geocode_module') || 'Geo::Coder::Googlev3';
+
+  my $geocoder = Geo::Coder::Googlev3->new;
+  my $location = $geocoder->geocode( location =>
+    $self->get($pre.'address1'). ','.
+    ( $self->get($pre.'address2') ? $self->get($pre.'address2').',' : '' ).
+    $self->get($pre.'city'). ','.
+    $self->get($pre.'state'). ','.
+    code2country($self->get($pre.'country'))
+  );
+
+  #errors?
+
+  my $geo_loc = $location->{'geometry'}{'location'} or return;
+  if ( $geo_loc->{'lat'} && $geo_loc->{'lng'} ) {
+    $self->set($pre.'latitude',  $geo_loc->{'lat'} );
+    $self->set($pre.'longitude', $geo_loc->{'lng'} );
+    $self->set($pre.'coord_auto', 'Y');
+  }
+
+}
+
 =item geocode DATA_VENDOR
 
 Returns a value for the customer location as encoded by DATA_VENDOR.
index 1bb66ed..19a71df 100644 (file)
@@ -894,6 +894,21 @@ sub _upgrade_data {  #class method
     die $error if $error;
   }
 
+  my @badlabels = qsearch({
+    'table' => 'part_svc_column',
+    'hashref' => {},
+    'extra_sql' => 'WHERE columnlabel IN ('.
+      "'Descriptive label for this particular device.',".
+      "'IP address.  Leave blank for automatic assignment.',".
+      "'Maximum upload speed for this service in Kbps.  0 denotes unlimited.',".
+      "'Maximum download speed for this service in Kbps.  0 denotes unlimited.')"
+  });
+  foreach my $col ( @badlabels ) {
+    $col->columnlabel('');
+    my $error = $col->replace;
+    die $error if $error;
+  }
+
 }
 
 =head1 BUGS
index 35de8b3..edcb4bc 100755 (executable)
@@ -346,10 +346,6 @@ sub check {
 
   return $x unless ref($x);
 
-  my $nw_coords = $conf->exists('svc_broadband-require-nw-coordinates');
-  my $lat_lower = $nw_coords ? 1 : -90;
-  my $lon_upper = $nw_coords ? -1 : 180;
-
   # remove delimiters
   my $mac_addr = uc($self->get('mac_addr'));
   $mac_addr =~ s/[-: ]//g;
@@ -365,8 +361,8 @@ sub check {
     || $self->ut_ipn('ip_addr')
     || $self->ut_hexn('mac_addr')
     || $self->ut_hexn('auth_key')
-    || $self->ut_coordn('latitude', $lat_lower, 90)
-    || $self->ut_coordn('longitude', -180, $lon_upper)
+    || $self->ut_coordn('latitude')
+    || $self->ut_coordn('longitude')
     || $self->ut_sfloatn('altitude')
     || $self->ut_textn('vlan_profile')
     || $self->ut_textn('plan_id')
@@ -399,6 +395,17 @@ sub check {
     }
   }
 
+  if ( $cust_pkg && ! $self->latitude && ! $self->longitude ) {
+    my $l = $cust_pkg->cust_location_or_main;
+    if ( $l->ship_latitude && $l->ship_longitude ) {
+      $self->latitude  = $l->ship_latitude;
+      $self->longitude = $l->ship_longitude;
+    } elsif ( $l->latitude && $l->longitude ) {
+      $self->latitude  = $l->latitude;
+      $self->longitude = $l->longitude;
+    }
+  }
+
   $error = $self->_check_ip_addr;
   return $error if $error;
 
index 3f60224..7b3b0b9 100644 (file)
@@ -55,6 +55,7 @@ Mihai Bazon<BR>
 Charles A. Beasley<BR>
 Stephen Bechard<BR>
 Eric Bosrup<BR>
+Dickie Bradford<BR>
 Dave Burgess<BR>
 Joe Camadine<BR>
 Chris Cappuccio<BR>
@@ -81,6 +82,7 @@ Foteos Macrides<BR>
 Roger Mangraviti<BR>
 mimooh<BR>
 Mack Nagashima<BR>
+David Peters<BR>
 Matt Peterson<BR>
 Luke Pfeifer<BR>
 Ricardo Signes<BR>
index d106b90..e0e40b7 100644 (file)
@@ -108,6 +108,10 @@ Perl backend version &copy; 2005 Nathan Schmidt
 Contains code derived from eps2png by Johan Vromans, licensed under the same
 terms as Perl (GPL/Artistic).
 
+<P>
+Contains code derived from HTML::GoogleMapsV3 by David Peters, licensed under
+the same terms as Perl (GPL/Artistic).
+
 <!-- artwork -->
 
 <P>
index 38b3513..2180155 100755 (executable)
@@ -51,6 +51,7 @@
 %    push @ship_style, 'background-color:#dddddd';
 %    foreach (
 %      qw( last first company address1 address2 city county state zip country
+%          latitude longitude coord_auto
 %          daytime night fax mobile )
 %    ) {
 %      $cust_main->set("ship_$_", $cust_main->get($_) );
@@ -73,7 +74,7 @@
 <SCRIPT>
 function bill_changed(what) {
   if ( what.form.same.checked ) {
-% for (qw( last first company address1 address2 city zip daytime night fax mobile )) { 
+% for (qw( last first company address1 address2 city zip latitude longitude coord_auto daytime night fax mobile )) { 
     what.form.ship_<%$_%>.value = what.form.<%$_%>.value;
 % } 
 
@@ -103,7 +104,7 @@ function samechanged(what) {
   if ( what.checked ) {
     bill_changed(what);
 
-%   my @fields = qw( last first company address1 address2 city city_select county state zip country daytime night fax mobile );
+%   my @fields = qw( last first company address1 address2 city city_select county state zip country latitude longitude daytime night fax mobile );
 %   for (@fields) { 
       what.form.ship_<%$_%>.disabled = true;
       what.form.ship_<%$_%>.style.backgroundColor = '#dddddd';
@@ -342,7 +343,7 @@ if ( $cgi->param('error') ) {
     my $cust_location = $qual->cust_location;
     $cust_location->dealternize;
     $cust_main->$_( $cust_location->$_ )
-      foreach qw( address1 address2 city county state zip country geocode );
+      foreach qw( address1 address2 city county state zip country latitude longitude coord_auto geocode );
 
     #locationnum -> package order
     $locationnum = $qual->locationnum;
index 13d5ada..49481d4 100644 (file)
@@ -23,6 +23,7 @@ my $args_callback = sub {
   my $cust_location = new FS::cust_location {
     map { $_ => scalar($cgi->param($_)) }
         qw( address1 address2 city county state zip country
+            latitude longitude
             location_kind location_type location_number
           )
   };
index ab01930..c8c8e98 100644 (file)
@@ -184,8 +184,10 @@ my $javascript = <<END;
       var c = f.company;
       if        ( f.residential_commercial_Residential.checked ) {
         c.disabled = true;
+        c.style.backgroundColor = '#dddddd';
       } else if ( f.residential_commercial_Commercial.checked ) {
         c.disabled = false;
+        c.style.backgroundColor = '#ffffff';
       }
     }
   </SCRIPT>
index 956d353..29495df 100644 (file)
@@ -123,6 +123,9 @@ my $pre = $opt{'prefix'};
 my $text_style   = $opt{'style'} ? [ @{ $opt{'style'} } ] : [];
 my $select_style = $opt{'style'} ? [ @{ $opt{'style'} } ] : [];
 
+push @$text_style,   @{ $opt{'text_style'} }   if $opt{'text_style'};
+push @$select_style, @{ $opt{'select_style'} } if $opt{'select_style'};
+
 my @cities = cities( $opt{'county'}, $opt{'state'}, $opt{'country'} );
 my $saved_city = '';
 if ( scalar(@cities) > 1 || $cities[0] ) {
diff --git a/httemplate/elements/coord-links.html b/httemplate/elements/coord-links.html
new file mode 100644 (file)
index 0000000..907e5f0
--- /dev/null
@@ -0,0 +1,22 @@
+<& /elements/init_overlib.html &>
+
+<& /elements/popup_link.html,
+     'action'      => $p. 'view/map.html?'. $query,
+     'label'       => mt('map'),
+     'actionlabel' => $name,
+     'width'       => 763,
+     'height'      => 575,
+     #'color'
+&>
+
+<A HREF="<%$p%>view/kml.cgi?<% $query %>"><% mt('earth') |h %></A>
+
+<%init>
+
+my ($latitude, $longitude, $name) = @_;
+
+my $query = 'name='. uri_escape($name).
+            ';lat='. $latitude.
+            ';lon='. $longitude;
+
+</%init>
index 48c6159..c5509c1 100644 (file)
@@ -149,7 +149,7 @@ Example:
 
 <TR>
   <<%$th%> ALIGN="right"><%$r%><% mt('City') |h %></<%$th%>>
-  <TD WIDTH="1"><% include('/elements/city.html', %select_hash) %></TD>
+  <TD WIDTH="1"><% include('/elements/city.html', %select_hash, 'text_style' => \@style ) %></TD>
   <<%$th%> ALIGN="right" WIDTH="1" ID="<%$pre%>countylabel" <%$county_style%>><%$r%>County</<%$th%>>
   <TD WIDTH="1"><% include('/elements/select-county.html', %select_hash ) %></TD>
   <<%$th%> ALIGN="right" WIDTH="1"><%$r%><% mt('State') |h %></<%$th%>>
@@ -175,6 +175,28 @@ Example:
   <TD COLSPAN=6><% include('/elements/select-country.html', %select_hash ) %></TD>
 </TR>
 
+<TR>
+  <TD ALIGN="right"><% mt('Latitude') |h %></TH>
+  <TD COLSPAN=7>
+    <INPUT TYPE  = "text"
+           NAME  = "<%$pre%>latitude"
+           ID    = "<%$pre%>latitude"
+           VALUE = "<% $object->get($pre.'latitude') |h %>"
+           <% $disabled %>
+           <% $style %>
+    >
+    <% mt('Longitude') |h %>
+    <INPUT TYPE  = "text"
+           NAME  = "<%$pre%>longitude"
+           ID    = "<%$pre%>longitude"
+           VALUE = "<% $object->get($pre.'longitude') |h %>"
+           <% $disabled %>
+           <% $style %>
+    >
+  </TD>
+</TR>
+<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->get($pre.'coord_auto') %>">
+
 % if ( !$pre ) { 
   <INPUT TYPE="hidden" NAME="geocode" VALUE="<% $opt{geocode} %>">
 % } else {
index fbb6ce3..e5f8c61 100644 (file)
@@ -46,6 +46,7 @@ if (ref($_[0]) eq 'HASH') {
 }
 
 my $label = $params->{'label'};
+$label =~ s/ /&nbsp;/g;
 my $onclick = include('/elements/popup_link_onclick.html', $params);
 
 </%init>
diff --git a/httemplate/elements/tr-coords.html b/httemplate/elements/tr-coords.html
new file mode 100644 (file)
index 0000000..5539f56
--- /dev/null
@@ -0,0 +1,14 @@
+<TR>
+  <TD ALIGN="right"><% mt('Latitude') |h %></TD>
+  <TD COLSPAN=5>
+    <FONT STYLE="background-color: #ffffff; border: 1px solid #ffffff"><% $latitude %></FONT>
+    &nbsp;<% mt('Longitude') |h %>
+    <FONT STYLE="background-color: #ffffff; border: 1px solid #ffffff"><% $longitude %></FONT>
+    <& /elements/coord-links.html, $latitude, $longitude, $name &>
+  </TD>
+</TR>
+<%init>
+
+my ($latitude, $longitude, $name) = @_;
+
+</%init>
index a876f62..0ca255b 100644 (file)
@@ -270,7 +270,9 @@ if ( $cgi->param('error') ) {
 my $editable = $cust_main ? 0 : 1; #could use explicit control
 my $addnew = $cust_main ? 1 : ( $locationnum>0 ? 0 : 1 );
 
-my @location_fields = qw( address1 address2 city county state zip country );
+my @location_fields = qw( address1 address2 city county state zip country
+                          latitude longitude
+                        );
 if ( $opt{'alt_format'} ) {
     push @location_fields, qw( location_type location_number location_kind );
 }
index fccdf02..3d4043a 100644 (file)
   <TD ALIGN="right"><% mt('Country') |h %></TD>
   <TD BGCOLOR="#ffffff"><% code2country( $cust_main->get("${pre}country") ) %></TD>
 </TR>
+
+% if ( $cust_main->get($pre.'latitude') && $cust_main->get($pre.'longitude') ) {
+  <& /elements/tr-coords.html, $cust_main->get($pre.'latitude'),
+                               $cust_main->get($pre.'longitude'),
+                               $cust_main->name_short,
+  &>
+% }
+
 <TR>
   <TD ALIGN="right"><% $daytime_label %></TD>
   <TD COLSPAN=3 BGCOLOR="#ffffff">
index 740d154..e16b2c1 100755 (executable)
@@ -26,7 +26,7 @@
 
 <TABLE>
   <TR>
-    <TD ALIGN="left">
+    <TD ALIGN="left" VALIGN="top">
 
 % if ( @$packages ) {
 
@@ -85,6 +85,7 @@
 % # in this format, put all packages in one section
 <& /elements/table-grid.html &>
 <& packages/section.html,
+    'cust_main'     => $cust_main,
     'packages'      => $packages,
     'show_location' => $show_location,
  &>
index 6658415..1bfca00 100644 (file)
@@ -1,15 +1,27 @@
-<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" WIDTH="20%">
 
 % unless ( $cust_pkg->locationnum ) {
   <I><FONT SIZE=-1>(<% mt('default service address') |h %>)</FONT><BR>
 % }
 
-  <% $loc->location_label( 'join_string'     => '<BR>',
-                           'double_space'    => ' &nbsp; ',
-                           'escape_function' => \&encode_entities,
-                           'countrydefault'  => $countrydefault,
-                         )
-  %>
+    <% $loc->location_label( 'join_string'     => '<BR>',
+                             'double_space'    => ' &nbsp; ',
+                             'escape_function' => \&encode_entities,
+                             'countrydefault'  => $countrydefault,
+                           )
+    %>
+
+%   if ( $loc->latitude && $loc->longitude ) {
+        <BR>
+        <FONT SIZE=-1>
+        <% $loc->latitude %>, <% $loc->longitude %>
+        <& /elements/coord-links.html,
+             $loc->latitude,
+             $loc->longitude,
+             $opt{'cust_main'}->name_short. ': '. $opt{'part_pkg'}->pkg
+        &>
+        </FONT>
+%   }
 
 % unless ( $cust_pkg->locationnum ) {
   </I>
 %      && $FS::CurrentUser::CurrentUser->access_right('Change customer package')
 %    )
 % {
+  <BR>
   <FONT SIZE=-1>
     (&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
 %   if ( $cust_pkg->locationnum ) {
-&nbsp;(&nbsp;<%edit_location_link($cust_pkg->locationnum)%>&nbsp;)
+        (&nbsp;<%edit_location_link($cust_pkg->locationnum)%>&nbsp;)
 %   }
   </FONT>
 % } 
index 20c9988..85f0c79 100755 (executable)
 %     }
 %
 %     my %iopt = (
-%       'bgcolor'  => $bgcolor,
-%       'cust_pkg' => $cust_pkg,
-%       'part_pkg' => $cust_pkg->part_pkg,
+%       'bgcolor'   => $bgcolor,
+%       'cust_pkg'  => $cust_pkg,
+%       'part_pkg'  => $cust_pkg->part_pkg,
+%       'cust_main' => $opt{'cust_main'},
 %       %conf_opt,
 %     );
 %
diff --git a/httemplate/view/kml.cgi b/httemplate/view/kml.cgi
new file mode 100644 (file)
index 0000000..47435c7
--- /dev/null
@@ -0,0 +1,13 @@
+<% $kml->archive %>\
+<%init>
+
+my ($latitude, $longitude, $name) = @_;
+#would be nice to pass in customer or prospect name too...
+
+my $kml = Geo::GoogleEarth::Pluggable->new;
+$kml->Point( map { $_=>scalar($cgi->param($_)) } qw( name lat lon ) );
+
+#http_header('Content-Type' => 'application/vnd.google-earth.kml+xml' ); #kml
+http_header('Content-Type' => 'application/vnd.google-earth.kmz' ); #kmz
+
+</%init>
diff --git a/httemplate/view/map.html b/httemplate/view/map.html
new file mode 100644 (file)
index 0000000..71a1538
--- /dev/null
@@ -0,0 +1,120 @@
+<& /elements/header-popup.html, {
+     title => '',#$name,
+     head  => $head,
+     etc   => 'onload="html_googlemaps_initialize()"',
+     nobr  => 1,
+   }
+&>
+
+<% $map_div %>
+
+<%init>
+
+my $name = js_string( scalar($cgi->param('name')) );
+
+my $point = [ map scalar($cgi->param($_)), qw( longitude latitude ) ];
+
+my( $head, $map_div ) = onload_render(
+  $name,
+  map scalar($cgi->param($_)), qw( lat lon )
+);
+
+#false laziness w/Mason.pm
+sub js_string {
+    my $string = shift;
+    $string =~ s/(['\\])/\\$1/g;
+    $string =~ s/\r/\\r/g;
+    $string =~ s/\n/\\n/g;
+    $string = "'". $string. "'";
+    return $string;
+}
+
+#subroutines below derived from HTML::GoogleMapsV3, but without using
+#Geo::Coder::Google or GPS::Point
+sub onload_render 
+{
+##     my $self = shift;
+        my( $name, $latitude, $longitude ) = @_;
+
+       #map_canvas { height: 100% }
+       
+       my $header='
+       <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+       <style type="text/css">
+               html { height: 100% }
+               body { height: 100%; margin: 0px; padding: 0px }
+               #map_canvas { height: 100% }
+       </style>
+       <script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=panoramio,geometry&v=3.4&sensor=false">
+       </script>
+       <script type="text/javascript">
+       var lengthLine=0;
+       function html_googlemaps_initialize() {
+    var latlng = new google.maps.LatLng(' .$latitude . ',' . $longitude . ');
+    var myOptions = {
+      zoom: 14,
+      center: latlng,
+      rotateControl: true,
+      mapTypeId: google.maps.MapTypeId.ROADMAP
+    };
+    
+    map = new google.maps.Map(document.getElementById("map_canvas"),
+        myOptions);
+    
+    map.setOptions( {rotateControl : true });
+    
+
+       ';
+
+##our own hacked in code for displaying a marker at the center
+$header .= '
+var markerOptions = {
+  map: map,
+  position: latlng,
+  title: '. $name. '
+};
+var marker = new google.maps.Marker(markerOptions);
+';
+
+##     if( defined $self->{polyline} ) {
+##             foreach my $polyline ( keys %{$self->{polyline}} ) {
+##                     $header .= $self->{polyline}->{$polyline} . "\n";
+##             }
+##     }
+       
+       $header .= '}
+       </script>';
+       
+       
+       #my $div = '<div id="map_canvas" style="width:80%; height:75%"></div>';
+       my $div = '<div id="map_canvas" style="width:100%; height:100%"></div>';
+
+
+       $header .= "<SCRIPT>
+       
+       panoramioLayer = new google.maps.panoramio.PanoramioLayer();
+       
+       function panoramioOn(){ 
+                                                               panoramioLayer.setMap(map);
+       }
+       function panoramioOff() {
+               panoramioLayer.setMap(null);
+       }
+       
+       function panoramioToggle() {
+               if( panoramioLayer.getMap() == null ) {
+                       panoramioOn(); 
+               } else {
+                       panoramioOff();
+               }
+       }       
+       
+
+               
+       </SCRIPT>";
+
+       return ($header,$div)
+       
+}
+
+</%init>
index d92d270..1c81956 100644 (file)
            )
         %>
       </TD>
-  </TR>
+    </TR>
+%   if ( $cust_location->latitude && $cust_location->longitude ) {
+      <& /elements/tr-coords.html, $cust_location->latitude,
+                                   $cust_location->longitude,
+                                   $prospect_main->name,
+      &>
+%   }
 % }
 
 </TABLE>
index 22cbb1f..de39f6a 100644 (file)
@@ -13,9 +13,17 @@ my %labels = map { $_ => ( ref($fields->{$_})
                           );
                  } keys %$fields;
 
+#my %labels = ();
+
+$labels{'description'} = emt('Description');
 $labels{'router'} = emt('Router');
+$labels{'speed_down'} = emt('Download Speed');
+$labels{'speed_up'} = emt('Upload Speed');
+$labels{'ip_addr'} = emt('IP Address');
 $labels{'usergroup'} = emt('RADIUS groups'); #?
 
+$labels{'coordinates'} = 'Latitude/Longitude';
+
 my @fields = (
   'description',
   { field => 'router', value => \&router },
@@ -24,8 +32,9 @@ my @fields = (
   { field => 'ip_addr', value => \&ip_addr },
   { field => 'sectornum', value => \&sectornum },
   'mac_addr',
-  'latitude',
-  'longitude',
+  #'latitude',
+  #'longitude',
+  { field => 'coordinates', value => \&coordinates },
   'altitude',
   'vlan_profile',
   'authkey',
@@ -46,8 +55,9 @@ sub router {
 sub ip_addr {
   my $svc = shift;
   my $ip_addr = $svc->ip_addr;
-  my $out = $ip_addr . ' (' . 
-    include('/elements/popup_link-ping.html', ip => $ip_addr) . ')';
+  my $out = $ip_addr;
+  $out .= ' (' . include('/elements/popup_link-ping.html', ip => $ip_addr) . ')'
+    if $ip_addr;
   if ( my $addr_block = $svc->addr_block ) {
     $out .= '<br>Netmask: ' . $addr_block->NetAddr->mask .
             '<br>Gateway: ' . $addr_block->ip_gateway;
@@ -72,4 +82,19 @@ sub sectornum {
   $link .  $tower_sector->description. ( $link ? '</A>' : '');
 }
 
+sub coordinates {
+  my $s = shift; #$svc_broadband
+  return '' unless $s->latitude && $s->longitude;
+
+  my $d = $s->description;
+  unless ($d) {
+    my $cust_pkg = $s->cust_svc->cust_pkg;
+    $d = $cust_pkg->cust_main->name_short if $cust_pkg;
+  }
+  
+  #'Latitude: '. $s->latitude. ', Longitude: '. $s->longitude. ' '.
+  $s->latitude. ', '. $s->longitude. ' '.
+    include('/elements/coord-links.html', $s->latitude, $s->longitude, $d);
+}
+
 </%init>