summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authorivan <ivan>2006-06-19 08:05:28 +0000
committerivan <ivan>2006-06-19 08:05:28 +0000
commit6b12c14cc10503d6b0783e8ef71fe44d9a9b37b6 (patch)
treef4adf16218b35f566763c8baaf4a1c41e1d81b6b /FS
parenta59c9cdd72fdf85d81007ba86e81479f6ec8e6e5 (diff)
add ability to select specific package defs. and package status to package report for qis
Diffstat (limited to 'FS')
-rw-r--r--FS/FS/Conf.pm29
-rw-r--r--FS/FS/ConfDefaults.pm68
-rw-r--r--FS/FS/UI/Web.pm126
-rw-r--r--FS/FS/cust_main_Mixin.pm44
-rw-r--r--FS/FS/cust_pkg.pm76
5 files changed, 277 insertions, 66 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index e7b9fa556..57c18e678 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -4,6 +4,7 @@ use vars qw($default_dir @config_items $DEBUG );
use IO::File;
use File::Basename;
use FS::ConfItem;
+use FS::ConfDefaults;
$DEBUG = 0;
@@ -1619,18 +1620,9 @@ httemplate/docs/config.html
{
'key' => 'cust-fields',
'section' => 'UI',
- 'description' => 'Which customer fields to display on reports',
+ 'description' => 'Which customer fields to display on reports by default',
'type' => 'select',
- 'select_enum' => [
- 'Customer: Last, First</b> or</i> Company (Last, First)</b>',
- '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 address if present)',
- 'Cust# | (bill) Customer | (service) Customer: custnum | Last, First or Company (Last, First) | (same for service address 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)',
- ],
+ 'select_hash' => [ FS::ConfDefaults->cust_fields_avail() ],
},
{
@@ -1709,6 +1701,21 @@ httemplate/docs/config.html
'type' => 'checkbox',
},
+ {
+ 'key' => 'batch-default_format',
+ 'section' => 'billing',
+ 'description' => 'Default format for batches.',
+ 'type' => 'select',
+ 'select_enum' => [ 'csv-td_canada_trust-merchant_pc_batch', 'BoM' ]
+ },
+
+ {
+ 'key' => 'batchconfig-BoM',
+ 'section' => 'billing',
+ 'description' => 'Configuration for Bank of Montreal batching, seven lines: 1. Origin ID, 2. Datacenter, 3. Typecode, 4. Short name, 5. Long name, 6. Bank, 7. Bank account',
+ 'type' => 'textarea',
+ },
+
);
1;
diff --git a/FS/FS/ConfDefaults.pm b/FS/FS/ConfDefaults.pm
new file mode 100644
index 000000000..b9cbcfbdf
--- /dev/null
+++ b/FS/FS/ConfDefaults.pm
@@ -0,0 +1,68 @@
+package FS::ConfDefaults;
+
+=head1 NAME
+
+FS::ConfDefaults - Freeside configuration default and available values
+
+=head1 SYNOPSIS
+
+ use FS::ConfDefaults;
+
+ @avail_cust_fields = FS::ConfDefaults->cust_fields_avail();
+
+=head1 DESCRIPTION
+
+Just a small class to keep config default and available values
+
+=head1 METHODS
+
+=over 4
+
+=item cust_fields_avail
+
+Returns a list, suitable for assigning to a hash, of available values and
+labels for customer fields values.
+
+=cut
+
+# 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)',
+
+); }
+
+=back
+
+=head1 BUGS
+
+Not yet.
+
+=head1 SEE ALSO
+
+L<FS::Conf>
+
+=cut
+
+1;
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index 10ddbf33f..080ac6e64 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -8,6 +8,8 @@ use FS::Record qw(dbdef);
#use FS::UI
#@ISA = qw( FS::UI );
+$DEBUG = 0;
+
use Date::Parse;
sub parse_beginning_ending {
my($cgi) = @_;
@@ -31,73 +33,116 @@ sub parse_beginning_ending {
}
###
-# cust_main report methods
+# cust_main report subroutines
###
-=item cust_header
-Returns an array of customer information headers according to the
-B<cust-fields> configuration setting.
+=item cust_header [ CUST_FIELDS_VALUE ]
+
+Returns an array of customer information headers according to the supplied
+customer fields value, or if no value is supplied, the B<cust-fields>
+configuration value.
=cut
use vars qw( @cust_fields );
-sub cust_sql_fields {
- my @fields = qw( last first company );
- push @fields, map "ship_$_", @fields
- if dbdef->table('cust_main')->column('ship_last');
- map "cust_main.$_", @fields;
-}
-
sub cust_header {
warn "FS::svc_Common::cust_header called"
if $DEBUG;
- my $conf = new FS::Conf;
-
my %header2method = (
- 'Customer' => 'name',
- 'Cust#' => 'custnum',
- 'Name' => 'contact',
- 'Company' => 'company',
- '(bill) Customer' => 'name',
- '(service) Customer' => 'ship_name',
- '(bill) Name' => 'contact',
- '(service) Name' => 'ship_contact',
- '(bill) Company' => 'company',
- '(service) Company' => 'ship_company',
+ 'Customer' => 'name',
+ 'Cust#' => 'custnum',
+ 'Name' => 'contact',
+ 'Company' => 'company',
+ '(bill) Customer' => 'name',
+ '(service) Customer' => 'ship_name',
+ '(bill) Name' => 'contact',
+ '(service) Name' => 'ship_contact',
+ '(bill) Company' => 'company',
+ '(service) Company' => 'ship_company',
+ 'Address 1' => 'address1',
+ 'Address 2' => 'address2',
+ 'City' => 'city',
+ 'State' => 'state',
+ 'Zip' => 'zip',
+ 'Country' => 'country_full',
+ 'Day phone' => 'daytime', # XXX should use msgcat, but how?
+ 'Night phone' => 'night', # XXX should use msgcat, but how?
+ 'Invoicing email(s)' => 'invoicing_list_emailonly',
);
+ my $cust_fields;
my @cust_header;
- if ( $conf->exists('cust-fields')
- && $conf->config('cust-fields') =~ /^([\w \|\#\(\)]+):/
- )
- {
- warn " found cust-fields configuration value"
- if $DEBUG;
+ if ( @_ && $_[0] ) {
- my $cust_fields = $1;
- @cust_header = split(/ \| /, $cust_fields);
- @cust_fields = map { $header2method{$_} } @cust_header;
- } else {
- warn " no cust-fields configuration value found; using default 'Customer'"
+ warn " using supplied cust-fields override".
+ " (ignoring cust-fields config file)"
if $DEBUG;
- @cust_header = ( 'Customer' );
- @cust_fields = ( 'name' );
+ $cust_fields = shift;
+
+ } else {
+
+ my $conf = new FS::Conf;
+ if ( $conf->exists('cust-fields')
+ && $conf->config('cust-fields') =~ /^([\w \|\#\(\)]+):?/
+ )
+ {
+ warn " found cust-fields configuration value"
+ if $DEBUG;
+ $cust_fields = $1;
+ } else {
+ warn " no cust-fields configuration value found; using default 'Customer'"
+ if $DEBUG;
+ $cust_fields = 'Customer';
+ }
+
}
+ @cust_header = split(/ \| /, $cust_fields);
+ @cust_fields = map { $header2method{$_} } @cust_header;
+
#my $svc_x = shift;
@cust_header;
}
-=item cust_fields
+=item cust_sql_fields [ CUST_FIELDS_VALUE ]
+
+Returns a list of fields for the SELECT portion of an SQL query.
+
+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_sql_fields {
+
+ my @fields = qw( last first company );
+ push @fields, map "ship_$_", @fields;
+ push @fields, 'country';
+
+ cust_header(@_);
+ #inefficientish, but tiny lists and only run once per page
+ push @fields,
+ grep { my $field = $_; grep { $_ eq $field } @cust_fields }
+ qw( address1 address2 city state zip daytime night );
+
+ map "cust_main.$_", @fields;
+}
+
+=item cust_fields SVC_OBJECT [ CUST_FIELDS_VALUE ]
Given a svc_ object that contains fields from cust_main (say, from a
JOINed search. See httemplate/search/svc_* for examples), returns an array
-of customer information according to the <B>cust-fields</B> configuration
-setting, or "(unlinked)" if this service is not linked to a customer.
+of customer information, or "(unlinked)" if this service is not linked to a
+customer.
+
+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
@@ -107,7 +152,8 @@ sub cust_fields {
"(cust_fields: @cust_fields)"
if $DEBUG > 1;
- cust_header() unless @cust_fields;
+ #cust_header(@_) unless @cust_fields; #now need to cache to keep cust_fields
+ # #override incase we were passed as a sub
my $seen_unlinked = 0;
map {
diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm
index a114c5a8a..aa4143df1 100644
--- a/FS/FS/cust_main_Mixin.pm
+++ b/FS/FS/cust_main_Mixin.pm
@@ -89,6 +89,50 @@ sub ship_contact {
: $self->cust_unlinked_msg;
}
+=item country_full
+
+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<country_full> method, or "(unlinked)" if this object is not
+linked to a customer.
+
+=cut
+
+sub country_full {
+ my $self = shift;
+ $self->cust_linked
+ ? FS::cust_main::country_full($self)
+ : $self->cust_unlinked_msg;
+}
+
+=item invoicing_list_emailonly
+
+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<country_full> method, or "(unlinked)" if this object is not
+linked to a customer.
+
+=cut
+
+sub invoicing_list_emailonly {
+ my $self = shift;
+ warn "invoicing_list_email only called on $self, ".
+ "custnum ". $self->custnum. "\n";
+ $self->cust_linked
+ ? FS::cust_main::invoicing_list_emailonly($self)
+ : $self->cust_unlinked_msg;
+}
+
+#read-only
+sub invoicing_list {
+ my $self = shift;
+ $self->cust_linked
+ ? FS::cust_main::invoicing_list($self)
+ : ();
+}
+
+=cut
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index 783cc73a3..ed9f2cbc6 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -2,6 +2,7 @@ package FS::cust_pkg;
use strict;
use vars qw(@ISA $disable_agentcheck @SVCDB_CANCEL_SEQ $DEBUG);
+use Tie::IxHash;
use FS::UID qw( getotaker dbh );
use FS::Misc qw( send_email );
use FS::Record qw( qsearch qsearchs );
@@ -824,26 +825,45 @@ Returns a short status string for this package, currently:
sub status {
my $self = shift;
+ my $freq = length($self->freq) ? $self->freq : $self->part_pkg->freq;
+
return 'cancelled' if $self->get('cancel');
return 'suspended' if $self->susp;
return 'not yet billed' unless $self->setup;
- return 'one-time charge' if $self->part_pkg->freq =~ /^(0|$)/;
+ return 'one-time charge' if $freq =~ /^(0|$)/;
return 'active';
}
-=item statuscolor
+=item statuses
-Returns a hex triplet color string for this package's status.
+Class method that returns the list of possible status strings for pacakges
+(see L<the status method|/status>). For example:
+
+ @statuses = FS::cust_pkg->statuses();
=cut
-my %statuscolor = (
+tie my %statuscolor, 'Tie::IxHash',
'not yet billed' => '000000',
'one-time charge' => '000000',
'active' => '00CC00',
'suspended' => 'FF9900',
'cancelled' => 'FF0000',
-);
+;
+
+sub statuses {
+ my $self = shift; #could be class...
+ grep { $_ !~ /^(not yet billed)$/ } #this is a dumb status anyway
+ # mayble split btw one-time vs. recur
+ keys %statuscolor;
+}
+
+=item statuscolor
+
+Returns a hex triplet color string for this package's status.
+
+=cut
+
sub statuscolor {
my $self = shift;
$statuscolor{$self->status};
@@ -1163,7 +1183,7 @@ sub reexport {
=back
-=head1 CLASS METHOD
+=head1 CLASS METHODS
=over 4
@@ -1178,6 +1198,17 @@ sub recurring_sql { "
where cust_pkg.pkgpart = part_pkg.pkgpart )
"; }
+=item onetime_sql
+
+Returns an SQL expression identifying one-time packages.
+
+=cut
+
+sub onetime_sql { "
+ '0' = ( select freq from part_pkg
+ where cust_pkg.pkgpart = part_pkg.pkgpart )
+"; }
+
=item active_sql
Returns an SQL expression identifying active packages.
@@ -1190,6 +1221,19 @@ sub active_sql { "
AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
"; }
+=item inactive_sql
+
+Returns an SQL expression identifying inactive packages (one-time packages
+that are otherwise unsuspended/uncancelled).
+
+=cut
+
+sub inactive_sql { "
+ ". $_[0]->onetime_sql(). "
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
+"; }
+
=item susp_sql
=item suspended_sql
@@ -1198,11 +1242,13 @@ Returns an SQL expression identifying suspended packages.
=cut
sub suspended_sql { susp_sql(@_); }
-sub susp_sql { "
- ". $_[0]->recurring_sql(). "
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0
-"; }
+sub susp_sql {
+ #$_[0]->recurring_sql(). ' AND '.
+ "
+ ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0
+ ";
+}
=item cancel_sql
=item cancelled_sql
@@ -1212,10 +1258,10 @@ Returns an SQL exprression identifying cancelled packages.
=cut
sub cancelled_sql { cancel_sql(@_); }
-sub cancel_sql { "
- ". $_[0]->recurring_sql(). "
- AND cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0
-"; }
+sub cancel_sql {
+ #$_[0]->recurring_sql(). ' AND '.
+ "cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0";
+}
=head1 SUBROUTINES