summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Conf.pm37
-rw-r--r--FS/FS/Mason.pm2
-rw-r--r--FS/FS/Record.pm23
-rw-r--r--FS/FS/Upgrade.pm3
-rw-r--r--FS/FS/cust_location.pm6
-rw-r--r--FS/FS/cust_main.pm41
-rw-r--r--FS/FS/geocode_Mixin.pm31
-rw-r--r--FS/FS/part_svc.pm15
-rwxr-xr-xFS/FS/svc_broadband.pm19
-rw-r--r--httemplate/docs/credits.html2
-rw-r--r--httemplate/docs/license.html4
-rwxr-xr-xhttemplate/edit/cust_main.cgi7
-rw-r--r--httemplate/edit/process/prospect_main.html1
-rw-r--r--httemplate/edit/prospect_main.html2
-rw-r--r--httemplate/elements/city.html3
-rw-r--r--httemplate/elements/coord-links.html22
-rw-r--r--httemplate/elements/location.html24
-rw-r--r--httemplate/elements/popup_link.html1
-rw-r--r--httemplate/elements/tr-coords.html14
-rw-r--r--httemplate/elements/tr-select-cust_location.html4
-rw-r--r--httemplate/view/cust_main/contacts.html8
-rwxr-xr-xhttemplate/view/cust_main/packages.html3
-rw-r--r--httemplate/view/cust_main/packages/location.html29
-rwxr-xr-xhttemplate/view/cust_main/packages/section.html7
-rw-r--r--httemplate/view/kml.cgi13
-rw-r--r--httemplate/view/map.html120
-rw-r--r--httemplate/view/prospect_main.html8
-rw-r--r--httemplate/view/svc_broadband.cgi33
28 files changed, 443 insertions, 39 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index fcdcd5766..efdad430a 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -2650,14 +2650,28 @@ and customer address. Include units.',
{
'key' => 'network_monitoring_system',
- 'section' => '',
+ 'section' => 'network_monitoring',
'description' => 'Networking monitoring system (NMS) integration. <b>Torrus_Internal</b> uses the built-in Torrus ticketing system (see the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:2.1:Documentation:Torrus_Installation">integrated networking monitoring system installation instructions</a>).',
'type' => 'select',
- #'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
'select_enum' => [ '', qw(Torrus_Internal) ],
},
{
+ 'key' => 'nms-auto_add-svc_ips',
+ 'section' => 'network_monitoring',
+ 'description' => 'Automatically add (and remove) IP addresses from these service tables to the network monitoring system.',
+ 'type' => 'selectmultiple',
+ 'select_enum' => [ 'svc_acct', 'svc_broadband', 'svc_dsl' ],
+ },
+
+ {
+ 'key' => 'nms-auto_add-community',
+ 'section' => 'network_monitoring',
+ 'description' => 'SNMP community string to use when automatically adding IP addresses from these services to the network monitoring system.',
+ 'type' => 'text',
+ },
+
+ {
'key' => 'ticket_system-default_queueid',
'section' => 'ticketing',
'description' => 'Default queue used when creating new customer tickets.',
@@ -3738,6 +3752,21 @@ and customer address. Include units.',
},
{
+ 'key' => 'geocode_module',
+ 'section' => '',
+ 'description' => 'Module to geocode (retrieve a latitude and longitude for) addresses',
+ 'type' => 'select',
+ 'select_enum' => [ 'Geo::Coder::Googlev3' ],
+ },
+
+ {
+ 'key' => 'geocode-require_nw_coordinates',
+ 'section' => 'UI',
+ 'description' => 'Require latitude and longitude in the North Western quadrant, e.g. for North American co-ordinates, etc.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'disable_acl_changes',
'section' => '',
'description' => 'Disable all ACL changes, for demos.',
@@ -4656,8 +4685,8 @@ and customer address. Include units.',
{
'key' => 'svc_broadband-require-nw-coordinates',
- 'section' => 'UI',
- 'description' => 'On svc_broadband add/edit, require latitude and longitude in the North Western quadrant, e.g. for North American co-ordinates, etc.',
+ 'section' => 'deprecated',
+ 'description' => 'Deprecated; see geocode-require_nw_coordinates instead',
'type' => 'checkbox',
},
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index 0cb2a0bff..773261f0f 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -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;
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index caddc6f91..677348728 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -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
@@ -57,18 +57,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
@@ -2343,11 +2350,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/^(-)//;
@@ -2395,7 +2408,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, @_);
diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm
index eac8333f1..3134b8c61 100644
--- a/FS/FS/Upgrade.pm
+++ b/FS/FS/Upgrade.pm
@@ -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', {});
diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm
index 7ffa5ed41..a3d5bcb3e 100644
--- a/FS/FS/cust_location.pm
+++ b/FS/FS/cust_location.pm
@@ -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;
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index a0a7e91ba..5c78d8a1f 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -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{$_});
}
diff --git a/FS/FS/geocode_Mixin.pm b/FS/FS/geocode_Mixin.pm
index c1b9f865b..9ac8e7a88 100644
--- a/FS/FS/geocode_Mixin.pm
+++ b/FS/FS/geocode_Mixin.pm
@@ -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.
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index cc30dbbd4..dea115cac 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -872,6 +872,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
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
index c5034b008..678a7889f 100755
--- a/FS/FS/svc_broadband.pm
+++ b/FS/FS/svc_broadband.pm
@@ -347,10 +347,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;
@@ -366,8 +362,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')
@@ -400,6 +396,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;
diff --git a/httemplate/docs/credits.html b/httemplate/docs/credits.html
index 3f6022478..7b3b0b93a 100644
--- a/httemplate/docs/credits.html
+++ b/httemplate/docs/credits.html
@@ -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>
diff --git a/httemplate/docs/license.html b/httemplate/docs/license.html
index d106b908e..e0e40b76e 100644
--- a/httemplate/docs/license.html
+++ b/httemplate/docs/license.html
@@ -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>
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index 38b351381..218015577 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -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;
diff --git a/httemplate/edit/process/prospect_main.html b/httemplate/edit/process/prospect_main.html
index 13d5ada7f..49481d44f 100644
--- a/httemplate/edit/process/prospect_main.html
+++ b/httemplate/edit/process/prospect_main.html
@@ -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
)
};
diff --git a/httemplate/edit/prospect_main.html b/httemplate/edit/prospect_main.html
index ab01930e5..c8c8e98e1 100644
--- a/httemplate/edit/prospect_main.html
+++ b/httemplate/edit/prospect_main.html
@@ -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>
diff --git a/httemplate/elements/city.html b/httemplate/elements/city.html
index 956d353bd..29495df43 100644
--- a/httemplate/elements/city.html
+++ b/httemplate/elements/city.html
@@ -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
index 000000000..907e5f04a
--- /dev/null
+++ b/httemplate/elements/coord-links.html
@@ -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>
diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html
index 48c6159bb..c5509c1a9 100644
--- a/httemplate/elements/location.html
+++ b/httemplate/elements/location.html
@@ -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 {
diff --git a/httemplate/elements/popup_link.html b/httemplate/elements/popup_link.html
index fbb6ce3b8..e5f8c61ca 100644
--- a/httemplate/elements/popup_link.html
+++ b/httemplate/elements/popup_link.html
@@ -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
index 000000000..5539f565e
--- /dev/null
+++ b/httemplate/elements/tr-coords.html
@@ -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>
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
index a876f6225..0ca255b3e 100644
--- a/httemplate/elements/tr-select-cust_location.html
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -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 );
}
diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html
index fccdf0247..3d4043aff 100644
--- a/httemplate/view/cust_main/contacts.html
+++ b/httemplate/view/cust_main/contacts.html
@@ -65,6 +65,14 @@
<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">
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 740d1544a..e16b2c1d4 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -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,
&>
diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html
index 6658415b5..1bfca00f2 100644
--- a/httemplate/view/cust_main/packages/location.html
+++ b/httemplate/view/cust_main/packages/location.html
@@ -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>
@@ -19,10 +31,11 @@
% && $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>
% }
diff --git a/httemplate/view/cust_main/packages/section.html b/httemplate/view/cust_main/packages/section.html
index 20c998880..85f0c795a 100755
--- a/httemplate/view/cust_main/packages/section.html
+++ b/httemplate/view/cust_main/packages/section.html
@@ -23,9 +23,10 @@
% }
%
% 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
index 000000000..47435c74a
--- /dev/null
+++ b/httemplate/view/kml.cgi
@@ -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
index 000000000..71a153842
--- /dev/null
+++ b/httemplate/view/map.html
@@ -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>
diff --git a/httemplate/view/prospect_main.html b/httemplate/view/prospect_main.html
index d92d27097..1c8195672 100644
--- a/httemplate/view/prospect_main.html
+++ b/httemplate/view/prospect_main.html
@@ -51,7 +51,13 @@
)
%>
</TD>
- </TR>
+ </TR>
+% if ( $cust_location->latitude && $cust_location->longitude ) {
+ <& /elements/tr-coords.html, $cust_location->latitude,
+ $cust_location->longitude,
+ $prospect_main->name,
+ &>
+% }
% }
</TABLE>
diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi
index 22cbb1f44..de39f6ae4 100644
--- a/httemplate/view/svc_broadband.cgi
+++ b/httemplate/view/svc_broadband.cgi
@@ -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>