summaryrefslogtreecommitdiff
path: root/FS/FS
diff options
context:
space:
mode:
Diffstat (limited to 'FS/FS')
-rw-r--r--FS/FS/AccessRight.pm7
-rw-r--r--FS/FS/ConfDefaults.pm44
-rw-r--r--FS/FS/UI/Web.pm95
-rw-r--r--FS/FS/cust_main.pm30
-rw-r--r--FS/FS/cust_main_Mixin.pm92
5 files changed, 232 insertions, 36 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index 038cb41..cc0bf7f 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -160,7 +160,7 @@ assigned to users and/or groups.
# report/listing rights...
###
'List customers',
- #'List zip codes',
+ 'List zip codes',
'List invoices',
'List packages',
'List services',
@@ -179,6 +179,11 @@ assigned to users and/or groups.
'Export', #
###
+# misc misc rights
+###
+ 'Raw SQL',
+
+###
# setup/config rights
###
'Edit advertising sources',
diff --git a/FS/FS/ConfDefaults.pm b/FS/FS/ConfDefaults.pm
index b9cbcfb..baee0bb 100644
--- a/FS/FS/ConfDefaults.pm
+++ b/FS/FS/ConfDefaults.pm
@@ -28,28 +28,28 @@ labels for customer fields values.
# XXX should use msgcat for "Day phone" and "Night phone", but how?
sub cust_fields_avail { (
- 'Customer' =>
- 'Last, First or Company (Last, First)',
- 'Cust# | Customer' =>
- 'custnum | Last, First or Company (Last, First)',
-
- 'Name | Company' =>
- 'Last, First | Company',
- 'Cust# | Name | Company' =>
- 'custnum | Last, First | Company',
-
- '(bill) Customer | (service) Customer' =>
- 'Last, First or Company (Last, First) | (same for service contact if present)',
- 'Cust# | (bill) Customer | (service) Customer' =>
- 'custnum | Last, First or Company (Last, First) | (same for service contact if present)',
-
- '(bill) Name | (bill) Company | (service) Name | (service) Company' =>
- 'Last, First | Company | (same for service address if present)',
- 'Cust# | (bill) Name | (bill) Company | (service) Name | (service) Company' =>
- 'custnum | Last, First | Company | (same for service address if present)',
-
- 'Cust# | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Invoicing email(s)' =>
- 'custnum | Last, First | Company | (all address fields ) | Day phone | Night phone | Invoicing email(s)',
+ 'Cust. Status | Customer' =>
+ 'Status | Last, First or Company (Last, First)',
+ 'Cust# | Cust. Status | Customer' =>
+ 'custnum | Status | Last, First or Company (Last, First)',
+
+ 'Cust. Status | Name | Company' =>
+ 'Status | Last, First | Company',
+ 'Cust# | Cust. Status | Name | Company' =>
+ 'custnum | Status | Last, First | Company',
+
+ 'Cust. Status | (bill) Customer | (service) Customer' =>
+ 'Status | Last, First or Company (Last, First) | (same for service contact if present)',
+ 'Cust# | Cust. Status | (bill) Customer | (service) Customer' =>
+ 'custnum | Status | Last, First or Company (Last, First) | (same for service contact if present)',
+
+ 'Cust. Status | (bill) Name | (bill) Company | (service) Name | (service) Company' =>
+ 'Status | Last, First | Company | (same for service address if present)',
+ 'Cust# | Cust. Status | (bill) Name | (bill) Company | (service) Name | (service) Company' =>
+ 'custnum | Status | Last, First | Company | (same for service address if present)',
+
+ 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Invoicing email(s)' =>
+ 'custnum | Status | Last, First | Company | (all address fields ) | Day phone | Night phone | Invoicing email(s)',
); }
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index 23f0e83..c815816 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -198,15 +198,16 @@ configuration value.
=cut
-use vars qw( @cust_fields );
+use vars qw( @cust_fields @cust_colors @cust_styles @cust_aligns );
sub cust_header {
- warn "FS::svc_Common::cust_header called"
+ warn "FS::UI:Web::cust_header called"
if $DEBUG;
my %header2method = (
'Customer' => 'name',
+ 'Cust. Status' => 'ucfirst_cust_status',
'Cust#' => 'custnum',
'Name' => 'contact',
'Company' => 'company',
@@ -227,6 +228,16 @@ sub cust_header {
'Invoicing email(s)' => 'invoicing_list_emailonly_scalar',
);
+ my %header2colormethod = (
+ 'Cust. Status' => 'cust_statuscolor',
+ );
+ my %header2style = (
+ 'Cust. Status' => 'b',
+ );
+ my %header2align = (
+ 'Cust. Status' => 'c',
+ );
+
my $cust_fields;
my @cust_header;
if ( @_ && $_[0] ) {
@@ -247,15 +258,24 @@ sub cust_header {
if $DEBUG;
$cust_fields = $1;
} else {
- warn " no cust-fields configuration value found; using default 'Customer'"
+ warn " no cust-fields configuration value found; using default 'Cust. Status | Customer'"
if $DEBUG;
- $cust_fields = 'Customer';
+ $cust_fields = 'Cust. Status | Customer';
}
}
@cust_header = split(/ \| /, $cust_fields);
@cust_fields = map { $header2method{$_} } @cust_header;
+ @cust_colors = map { exists $header2colormethod{$_}
+ ? $header2colormethod{$_}
+ : ''
+ }
+ @cust_header;
+ @cust_styles = map { exists $header2style{$_} ? $header2style{$_} : '' }
+ @cust_header;
+ @cust_aligns = map { exists $header2align{$_} ? $header2align{$_} : 'l' }
+ @cust_header;
#my $svc_x = shift;
@cust_header;
@@ -286,9 +306,9 @@ sub cust_sql_fields {
map "cust_main.$_", @fields;
}
-=item cust_fields SVC_OBJECT [ CUST_FIELDS_VALUE ]
+=item cust_fields OBJECT [ CUST_FIELDS_VALUE ]
-Given a svc_ object that contains fields from cust_main (say, from a
+Given an object that contains fields from cust_main (say, from a
JOINed search. See httemplate/search/svc_* for examples), returns an array
of customer information, or "(unlinked)" if this service is not linked to a
customer.
@@ -301,7 +321,7 @@ setting is supplied, the <B>cust-fields</B> configuration value.
sub cust_fields {
my $svc_x = shift;
- warn "FS::svc_Common::cust_fields called for $svc_x ".
+ warn "FS::UI::Web::cust_fields called for $svc_x ".
"(cust_fields: @cust_fields)"
if $DEBUG > 1;
@@ -322,6 +342,67 @@ sub cust_fields {
} @cust_fields;
}
+=item cust_colors
+
+Returns an array of subroutine references (or empty strings) for returning
+customer information colors.
+
+As with L<the cust_header subroutine|/cust_header>, the fields returned are
+defined by the supplied customer fields setting, or if no customer fields
+setting is supplied, the <B>cust-fields</B> configuration value.
+
+=cut
+
+sub cust_colors {
+ map {
+ my $method = $_;
+ if ( $method ) {
+ sub { shift->$method(@_) };
+ } else {
+ '';
+ }
+ } @cust_colors;
+}
+
+=item cust_styles
+
+Returns an array of customer information styles.
+
+As with L<the cust_header subroutine|/cust_header>, the fields returned are
+defined by the supplied customer fields setting, or if no customer fields
+setting is supplied, the <B>cust-fields</B> configuration value.
+
+=cut
+
+sub cust_styles {
+ map {
+ if ( $_ ) {
+ $_;
+ } else {
+ '';
+ }
+ } @cust_styles;
+}
+
+=item cust_aligns
+
+Returns an array or scalar (depending on context) of customer information
+alignments.
+
+As with L<the cust_header subroutine|/cust_header>, the fields returned are
+defined by the supplied customer fields setting, or if no customer fields
+setting is supplied, the <B>cust-fields</B> configuration value.
+
+=cut
+
+sub cust_aligns {
+ if ( wantarray ) {
+ @cust_aligns;
+ } else {
+ join('', @cust_aligns);
+ }
+}
+
###
# begin JSRPC code...
###
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 1daf6ba..e1708cc 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -3886,6 +3886,8 @@ sub country_full {
code2country($self->country);
}
+=item cust_status
+
=item status
Returns a status string for this customer, currently:
@@ -3906,17 +3908,35 @@ Returns a status string for this customer, currently:
=cut
-sub status {
+sub status { shift->cust_status(@_); }
+
+sub cust_status {
my $self = shift;
for my $status (qw( prospect active inactive suspended cancelled )) {
my $method = $status.'_sql';
my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g;
my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr;
- $sth->execute( ($self->custnum) x $numnum ) or die $sth->errstr;
+ $sth->execute( ($self->custnum) x $numnum )
+ or die "Error executing 'SELECT $sql': ". $sth->errstr;
return $status if $sth->fetchrow_arrayref->[0];
}
}
+=item ucfirst_cust_status
+
+=item ucfirst_status
+
+Returns the status with the first character capitalized.
+
+=cut
+
+sub ucfirst_status { shift->ucfirst_cust_status(@_); }
+
+sub ucfirst_cust_status {
+ my $self = shift;
+ ucfirst($self->cust_status);
+}
+
=item statuscolor
Returns a hex triplet color string for this customer's status.
@@ -3932,9 +3952,11 @@ use vars qw(%statuscolor);
'cancelled' => 'FF0000', #red
);
-sub statuscolor {
+sub statuscolor { shift->cust_statuscolor(@_); }
+
+sub cust_statuscolor {
my $self = shift;
- $statuscolor{$self->status};
+ $statuscolor{$self->cust_status};
}
=back
diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm
index 3952f19..fbfb8c2 100644
--- a/FS/FS/cust_main_Mixin.pm
+++ b/FS/FS/cust_main_Mixin.pm
@@ -2,9 +2,10 @@ package FS::cust_main_Mixin;
use strict;
use vars qw( $DEBUG );
+use FS::UID qw(dbh);
use FS::cust_main;
-$DEBUG = 0;
+$DEBUG = 1;
=head1 NAME
@@ -138,7 +139,7 @@ this object is not linked to a customer.
sub invoicing_list_emailonly_scalar {
my $self = shift;
- warn "invoicing_list_email only called on $self, ".
+ warn "invoicing_list_emailonly called on $self, ".
"custnum ". $self->custnum. "\n"
if $DEBUG;
$self->cust_linked
@@ -165,8 +166,95 @@ sub invoicing_list {
: ();
}
+=item status
+
+Given an object that contains fields from cust_main (say, from a JOINed
+search; see httemplate/search/ for examples), returns the equivalent of the
+FS::cust_main I<status> method, or "(unlinked)" if this object is not linked to
+a customer.
+
+=cut
+
+sub cust_status {
+ my $self = shift;
+ return $self->cust_unlinked_msg unless $self->cust_linked;
+
+ #FS::cust_main::status($self)
+ #false laziness w/actual cust_main::status
+ # (make sure FS::cust_main methods are called)
+ for my $status (qw( prospect active inactive suspended cancelled )) {
+ my $method = $status.'_sql';
+ my $sql = FS::cust_main->$method();;
+ my $numnum = ( $sql =~ s/cust_main\.custnum/?/g );
+ my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr;
+ $sth->execute( ($self->custnum) x $numnum )
+ or die "Error executing 'SELECT $sql': ". $sth->errstr;
+ return $status if $sth->fetchrow_arrayref->[0];
+ }
+}
+
+=item ucfirst_cust_status
+
+Given an object that contains fields from cust_main (say, from a JOINed
+search; see httemplate/search/ for examples), returns the equivalent of the
+FS::cust_main I<ucfirst_status> method, or "(unlinked)" if this object is not
+linked to a customer.
+
+=cut
+
+sub ucfirst_cust_status {
+ my $self = shift;
+ $self->cust_linked
+ ? ucfirst( $self->cust_status(@_) )
+ : $self->cust_unlinked_msg;
+}
+
+=item cust_statuscolor
+
+Given an object that contains fields from cust_main (say, from a JOINed
+search; see httemplate/search/ for examples), returns the equivalent of the
+FS::cust_main I<statuscol> method, or "000000" if this object is not linked to
+a customer.
+
=cut
+sub cust_statuscolor {
+ my $self = shift;
+
+ $self->cust_linked
+ ? FS::cust_main::cust_statuscolor($self)
+ : '000000';
+}
+
+=item prospect_sql
+
+=item active_sql
+
+=item inactive_sql
+
+=item suspended_sql
+
+=item cancelled_sql
+
+Given an object that contains fields from cust_main (say, from a JOINed
+search; see httemplate/search/ for examples), returns the equivalent of the
+corresponding FS::cust_main method, or "0" if this object is not linked to
+a customer.
+
+=cut
+
+foreach my $sub (qw( prospect active inactive suspended cancelled )) {
+ eval "
+ sub ${sub}_sql {
+ my \$self = shift;
+ \$self->cust_linked
+ ? FS::cust_main::${sub}_sql(\$self)
+ : '0';
+ }
+ ";
+ die $@ if $@;
+}
+
=back
=head1 BUGS