summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormark <mark>2010-12-29 22:56:47 +0000
committermark <mark>2010-12-29 22:56:47 +0000
commit6fc8a42e503e4e1f12659e1cfef7f5f26577034f (patch)
treefcac659b42217a4013afe04a98ac956f2c650cdb
parent15a9fae1bde88fb279534de4effae20e43fbee27 (diff)
cust_location editing features, RT#10766
-rw-r--r--FS/FS/Schema.pm1
-rw-r--r--FS/FS/cust_location.pm69
-rwxr-xr-xhttemplate/edit/cust_location.cgi54
-rw-r--r--httemplate/edit/process/cust_location.cgi38
-rw-r--r--httemplate/elements/tr-select-cust_location.html1
-rwxr-xr-xhttemplate/misc/disable-cust_location.cgi35
-rwxr-xr-xhttemplate/view/cust_main/packages.html96
-rw-r--r--httemplate/view/cust_main/packages/location.html13
-rwxr-xr-xhttemplate/view/cust_main/packages/section.html95
9 files changed, 325 insertions, 77 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 1a88dd2a9..cd0a4dc2f 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -906,6 +906,7 @@ sub tables_hashref {
'zip', 'varchar', 'NULL', 10, '', '',
'country', 'char', '', 2, '', '',
'geocode', 'varchar', 'NULL', 20, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'locationnum',
'unique' => [],
diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm
index ab80941f9..60c0181a3 100644
--- a/FS/FS/cust_location.pm
+++ b/FS/FS/cust_location.pm
@@ -3,6 +3,7 @@ package FS::cust_location;
use strict;
use base qw( FS::geocode_Mixin FS::Record );
use Locale::Country;
+use FS::UID qw( dbh );
use FS::Record qw( qsearch ); #qsearchs );
use FS::prospect_main;
use FS::cust_main;
@@ -74,6 +75,10 @@ Country (see L<FS::cust_main_county>)
Geocode
+=item disabled
+
+Disabled flag; set to 'Y' to disable the location.
+
=back
=head1 METHODS
@@ -192,6 +197,70 @@ city, county, state, zip, country, geocode.
=cut
+=item move_to HASHREF
+
+Takes a hashref with one or more cust_location fields. Creates a duplicate
+of the existing location with all fields set to the values in the hashref.
+Moves all packages that use the existing location to the new one, then sets
+the "disabled" flag on the old location. Returns nothing on success, an
+error message on error.
+
+=cut
+
+sub move_to {
+ my $old = shift;
+ my $hashref = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+ my $error = '';
+
+ my $new = FS::cust_location->new({
+ $old->location_hash,
+ 'custnum' => $old->custnum,
+ 'prospectnum' => $old->prospectnum,
+ %$hashref
+ });
+ $error = $new->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error creating location: $error";
+ }
+
+ my @pkgs = qsearch('cust_pkg', {
+ 'locationnum' => $old->locationnum,
+ 'cancel' => ''
+ });
+ foreach my $cust_pkg (@pkgs) {
+ $error = $cust_pkg->change(
+ 'locationnum' => $new->locationnum,
+ 'keep_dates' => 1
+ );
+ if ( $error and not ref($error) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error moving pkgnum ".$cust_pkg->pkgnum.": $error";
+ }
+ }
+
+ $old->disabled('Y');
+ $error = $old->replace;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error disabling old location: $error";
+ }
+
+ $dbh->commit if $oldAutoCommit;
+ return;
+}
+
=back
=head1 BUGS
diff --git a/httemplate/edit/cust_location.cgi b/httemplate/edit/cust_location.cgi
new file mode 100755
index 000000000..80b27c2b3
--- /dev/null
+++ b/httemplate/edit/cust_location.cgi
@@ -0,0 +1,54 @@
+<% include('/elements/header-popup.html', "Edit Location") %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="EditLocationForm"
+ACTION="<% $p %>edit/process/cust_location.cgi" METHOD=POST>
+<INPUT TYPE="hidden" NAME="locationnum" VALUE="<% $locationnum %>">
+
+<% ntable('#cccccc') %>
+<% include('/elements/location.html',
+ 'object' => $cust_location,
+ 'no_asterisks' => 1,
+ ) %>
+</TABLE>
+
+<BR>
+<SCRIPT TYPE="text/javascript">
+function areyousure() {
+ return confirm('Modify this service location?');
+}
+</SCRIPT>
+<INPUT TYPE="submit" VALUE="Submit" onclick="return areyousure()">
+
+</FORM>
+</BODY>
+</HTML>
+
+<%init>
+
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+# it's the same access right you'd need to do this by editing packages
+die "access denied"
+ unless $curuser->access_right('Change customer package');
+
+my $locationnum = scalar($cgi->param('locationnum'));
+my $cust_location = qsearchs({
+ 'select' => 'cust_location.*',
+ 'table' => 'cust_location',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'locationnum' => $locationnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+ }) or die "unknown locationnum $locationnum";
+
+die "can't edit disabled locationnum $locationnum" if $cust_location->disabled;
+
+my $cust_main = qsearchs('cust_main', { 'custnum' => $cust_location->custnum })
+ or die "can't get cust_main record for custnum ". $cust_location->custnum;
+
+my @cust_pkgs = qsearch('cust_pkg', { 'locationnum' => $locationnum });
+
+</%init>
diff --git a/httemplate/edit/process/cust_location.cgi b/httemplate/edit/process/cust_location.cgi
new file mode 100644
index 000000000..790fc8ea4
--- /dev/null
+++ b/httemplate/edit/process/cust_location.cgi
@@ -0,0 +1,38 @@
+% if ($error) {
+% $cgi->param('error', Dumper($error));
+% $cgi->redirect(popurl(3). 'edit/cust_location.cgi?'. $cgi->query_string );
+% } else {
+
+ <% header("Location changed") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+ </BODY>
+ </HTML>
+
+% }
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Change customer package');
+
+my $locationnum = $cgi->param('locationnum');
+my $cust_location = qsearchs({
+ 'select' => 'cust_location.*',
+ 'table' => 'cust_location',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'locationnum' => $locationnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+die "unknown locationnum $locationnum" unless $cust_location;
+
+my $new = {
+ map { $_ => scalar($cgi->param($_)) }
+ qw( address1 address2 city county state zip country )
+};
+
+my $error = $cust_location->move_to($new);
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
index f2b267a8b..6de034669 100644
--- a/httemplate/elements/tr-select-cust_location.html
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -151,6 +151,7 @@ Example:
% push @locations, $cust_location
% if !$cust_main && $cust_location && $cust_location->locationnum>0;
% foreach my $loc ( sort $location_sort @locations ) {
+% next if $loc->disabled;
<OPTION VALUE="<% $loc->locationnum %>"
<% $locationnum == $loc->locationnum ? 'SELECTED' : '' %>
><% $loc->line |h %>
diff --git a/httemplate/misc/disable-cust_location.cgi b/httemplate/misc/disable-cust_location.cgi
new file mode 100755
index 000000000..ee7ba1dbc
--- /dev/null
+++ b/httemplate/misc/disable-cust_location.cgi
@@ -0,0 +1,35 @@
+<% header("Location disabled") %>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $error;
+
+die "access denied"
+ unless $curuser->access_right('Change customer package');
+
+my $locationnum = $cgi->param('locationnum');
+my $cust_location = qsearchs({
+ 'select' => 'cust_location.*',
+ 'table' => 'cust_location',
+ 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
+ 'hashref' => { 'locationnum' => $locationnum },
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
+});
+die "unknown locationnum $locationnum" unless $cust_location;
+
+my @pkgs = qsearch('cust_pkg', { 'locationnum' => $locationnum,
+ 'cancel' => '' });
+if ( @pkgs ) {
+ $error = "Location $locationnum has active packages"
+}
+else {
+ $cust_location->disabled('Y');
+ $error = $cust_location->replace;
+}
+die $error if $error;
+</%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 17b7c9537..e21c62451 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -65,61 +65,23 @@ Current packages
<TR>
<TD COLSPAN=2>
-
-% if ( @$packages ) {
-
-<% include('/elements/table-grid.html') %>
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = '';
-
-<TR>
- <TH CLASS="grid" BGCOLOR="#cccccc">Package</TH>
- <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
-% if ( $show_location ) {
- <TH CLASS="grid" BGCOLOR="#cccccc">Location</TH>
-% }
- <TH CLASS="grid" BGCOLOR="#cccccc">Services</TH>
-</TR>
-
-% #$FS::cust_pkg::DEBUG = 2;
-% foreach my $cust_pkg (@$packages) {
-%
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-%
-% my %iopt = (
-% 'bgcolor' => $bgcolor,
-% 'cust_pkg' => $cust_pkg,
-% 'part_pkg' => $cust_pkg->part_pkg,
-% %conf_opt,
-% );
-%
-
- <!--pkgnum: <% $cust_pkg->pkgnum %>-->
- <TR>
- <% include('packages/package.html', %iopt) %>
- <% include('packages/status.html', %iopt) %>
-% if ( $show_location ) {
- <% include('packages/location.html', %iopt) %>
+% if ( $conf->exists('cust_pkg-group_by_location') and $show_location ) {
+<% include('locations.html',
+ 'cust_main' => $cust_main,
+ 'packages' => $packages,
+) %>
% }
- <% include('packages/services.html', %iopt) %>
- </TR>
-
-% }
-
+% else {
+% # in this format, put all packages in one section
+<% include('/elements/table-grid.html') %>
+<% include('packages/section.html',
+ 'packages' => $packages,
+ 'show_location' => $show_location,
+) %>
</TABLE>
-
-% } else {
-<BR>
-% }
-
+% }
</TD>
</TR>
-</TABLE>
% if ( $cgi->param('fragment') =~ /^cust_pkg(\d+)$/ ) {
<SCRIPT>
@@ -130,42 +92,22 @@ Current packages
if ( el ) el.scrollIntoView(true);
</SCRIPT>
% }
-
+</TABLE>
<%init>
-my( $cust_main ) = @_;
+my $cust_main = shift;
+my %opt = @_;
my $conf = new FS::Conf;
my $curuser = $FS::CurrentUser::CurrentUser;
my( $packages, $num_old_packages ) = get_packages($cust_main, $conf);
-my $show_location = $conf->exists('cust_pkg-always_show_location')
- || ( grep $_->locationnum, @$packages ); # ? '1' : '0';
-my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
-my %conf_opt = (
- #for services.html and status.html
- 'cust_pkg-display_times' => ($conf->exists('cust_pkg-display_times')
- || $curuser->option('cust_pkg-display_times')),
- #for status.html
- 'cust_pkg-show_autosuspend' => $conf->exists('cust_pkg-show_autosuspend'),
- #for status.html pkg-balances
- 'pkg-balances' => $conf->exists('pkg-balances'),
- 'money_char' => ( $conf->config('money_char') || '$' ),
-
- #for location.html
- 'countrydefault' => $countrydefault,
- 'statedefault' => ( scalar($conf->config('statedefault'))
- || ($countrydefault eq 'US' ? 'CA' : '') ),
- #for services.html
- 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'),
- 'legacy_link' => $conf->exists('legacy_link'),
- 'svc_broadband-manage_link' => scalar($conf->config('svc_broadband-manage_link')),
- 'maestro-status_test' => $conf->exists('maestro-status_test'),
- 'cust_pkg-large_pkg_size' => $conf->config('cust_pkg-large_pkg_size'),
-);
+my $show_location = $conf->exists('cust_pkg-always_show_location')
+ || (grep $_->locationnum, @$packages); # ? '1' : '0';
+my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
#subroutines
sub get_packages {
diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html
index 41155cbae..40a7de59f 100644
--- a/httemplate/view/cust_main/packages/location.html
+++ b/httemplate/view/cust_main/packages/location.html
@@ -21,12 +21,16 @@
% {
<FONT SIZE=-1>
(&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
+% if ( $cust_pkg->locationnum ) {
+&nbsp;(&nbsp;<%edit_location_link($cust_pkg->locationnum)%>&nbsp;)
+% }
</FONT>
% }
</TD>
<%init>
+my $conf = new FS::Conf;
my %opt = @_;
my $bgcolor = $opt{'bgcolor'};
@@ -50,4 +54,13 @@ sub pkg_change_location_link {
);
}
+sub edit_location_link {
+ my $locationnum = shift;
+ include( '/elements/popup_link.html',
+ 'action' => $p. "edit/cust_location.cgi?locationnum=$locationnum",
+ 'label' => 'Edit&nbsp;location',
+ 'actionlabel' => 'Edit',
+ );
+}
+
</%init>
diff --git a/httemplate/view/cust_main/packages/section.html b/httemplate/view/cust_main/packages/section.html
new file mode 100755
index 000000000..45365a003
--- /dev/null
+++ b/httemplate/view/cust_main/packages/section.html
@@ -0,0 +1,95 @@
+% if ( @$packages ) {
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+% #my $width = $show_location ? 'WIDTH="25%"' : 'WIDTH="33%"';
+ <TH CLASS="grid" BGCOLOR="#cccccc">Package</TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH>
+% if ( $show_location ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc">Location</TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc">Services</TH>
+</TR>
+
+% #$FS::cust_pkg::DEBUG = 2;
+% foreach my $cust_pkg (@$packages) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my %iopt = (
+% 'bgcolor' => $bgcolor,
+% 'cust_pkg' => $cust_pkg,
+% 'part_pkg' => $cust_pkg->part_pkg,
+% %conf_opt,
+% );
+%
+
+ <!--pkgnum: <% $cust_pkg->pkgnum %>-->
+ <TR>
+ <% include('package.html', %iopt) %>
+ <% include('status.html', %iopt) %>
+% if ( $show_location ) {
+ <% include('location.html', %iopt) %>
+% }
+ <% include('services.html', %iopt) %>
+ </TR>
+
+% } #foreach $cust_pkg
+%# </TABLE>
+% } #if @$packages
+% else {
+<BR>
+% }
+
+<%init>
+
+my %opt = @_;
+my $conf = new FS::Conf;
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $packages = $opt{'packages'};
+my $show_location = $opt{'show_location'};
+
+# Sort order is hardcoded for now, can change this if needed.
+@$packages = sort {
+ ( $a->getfield('cancel') <=> $b->getfield('cancel') ) or
+ ( $a->getfield('setup') <=> $b->getfield('setup') ) or
+ ( $a->getfield('pkgnum') <=> $b->getfield('pkgnum') )
+} @$packages;
+
+my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
+
+my %conf_opt = (
+ #for services.html and status.html
+ 'cust_pkg-display_times' => ($conf->exists('cust_pkg-display_times')
+ || $curuser->option('cust_pkg-display_times')),
+ #for status.html
+ 'cust_pkg-show_autosuspend' => $conf->exists('cust_pkg-show_autosuspend'),
+ #for status.html pkg-balances
+ 'pkg-balances' => $conf->exists('pkg-balances'),
+ 'money_char' => ( $conf->config('money_char') || '$' ),
+
+ #for location.html
+ 'countrydefault' => $countrydefault,
+ 'statedefault' => ( scalar($conf->config('statedefault'))
+ || ($countrydefault eq 'US' ? 'CA' : '') ),
+ #for services.html
+ 'svc_external-skip_manual' => $conf->exists('svc_external-skip_manual'),
+ 'legacy_link' => $conf->exists('legacy_link'),
+ 'svc_broadband-manage_link' => scalar($conf->config('svc_broadband-manage_link')),
+ 'maestro-status_test' => $conf->exists('maestro-status_test'),
+ 'cust_pkg-large_pkg_size' => $conf->config('cust_pkg-large_pkg_size'),
+
+ # for packages.html Change location link
+ 'show_location' => $show_location,
+);
+
+
+</%init>