summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/AccessRight.pm2
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm13
-rw-r--r--FS/FS/Conf.pm33
-rw-r--r--FS/FS/Record.pm5
-rw-r--r--FS/FS/Report/Table.pm2
-rw-r--r--FS/FS/Schema.pm17
-rw-r--r--FS/FS/Template_Mixin.pm9
-rw-r--r--FS/FS/UI/Web.pm8
-rw-r--r--FS/FS/cdr.pm2
-rw-r--r--FS/FS/contact_phone.pm11
-rw-r--r--FS/FS/cust_bill.pm9
-rw-r--r--FS/FS/cust_main.pm15
-rw-r--r--FS/FS/cust_main/Search.pm22
-rw-r--r--FS/FS/cust_pay.pm1
-rw-r--r--FS/FS/cust_pay_batch.pm3
-rw-r--r--FS/FS/cust_pay_pending.pm1
-rw-r--r--FS/FS/cust_pay_void.pm2
-rw-r--r--FS/FS/cust_pkg.pm5
-rw-r--r--FS/FS/cust_refund.pm1
-rw-r--r--FS/FS/part_event/Action/letter.pm1
-rw-r--r--FS/FS/part_event/Action/notice.pm1
-rw-r--r--FS/FS/part_event/Action/notice_to.pm1
-rw-r--r--FS/FS/part_event/Action/svc_acct_notice.pm1
-rw-r--r--FS/FS/part_export/rt_ticket.pm2
-rw-r--r--FS/FS/part_export/send_email.pm2
-rw-r--r--FS/FS/part_export/shellcommands.pm8
-rw-r--r--FS/FS/part_pkg/bulk_Common.pm11
-rw-r--r--FS/FS/queue.pm29
-rw-r--r--FS/FS/svc_MAC_Mixin.pm65
-rwxr-xr-xFS/FS/svc_broadband.pm19
-rw-r--r--FS/FS/svc_cable.pm20
-rw-r--r--FS/FS/svc_phone.pm26
-rw-r--r--FS/bin/freeside-queued3
-rwxr-xr-xFS/bin/freeside-upgrade7
-rw-r--r--bin/restore-ship_company32
-rw-r--r--bin/test_scrub12
-rw-r--r--fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm17
-rw-r--r--httemplate/browse/msg_template.html29
-rwxr-xr-xhttemplate/edit/cust_main.cgi2
-rw-r--r--httemplate/edit/cust_main/before_ship_location.html13
-rw-r--r--httemplate/edit/cust_main/contact.html45
-rw-r--r--httemplate/edit/elements/edit.html2
-rwxr-xr-xhttemplate/edit/process/cust_main.cgi4
-rw-r--r--httemplate/edit/process/detach-cust_pkg.html15
-rw-r--r--httemplate/elements/create_uri_query21
-rw-r--r--httemplate/elements/handle_uri_query12
-rw-r--r--httemplate/elements/pager.html17
-rw-r--r--httemplate/elements/searchbar-cust_main.html2
-rw-r--r--httemplate/elements/tr-censustract.html23
-rw-r--r--httemplate/elements/tr-cust_main-phones.html45
-rw-r--r--httemplate/elements/tr-select-cust_location.html9
-rwxr-xr-xhttemplate/misc/detach_pkg.html19
-rw-r--r--httemplate/misc/disable-msg_template.cgi77
-rw-r--r--httemplate/misc/email-customers.html1
-rw-r--r--httemplate/search/cust_bill_pkg.cgi5
-rw-r--r--httemplate/view/cust_main/contacts.html10
-rwxr-xr-xhttemplate/view/cust_main/locations.html49
-rw-r--r--httemplate/view/cust_main/misc.html11
-rw-r--r--httemplate/view/cust_main/packages/location.html72
59 files changed, 678 insertions, 223 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm
index ca96eb52f..4c99c7cb8 100644
--- a/FS/FS/AccessRight.pm
+++ b/FS/FS/AccessRight.pm
@@ -236,7 +236,7 @@ tie my %rights, 'Tie::IxHash',
# customer voiding rights..
###
'Customer payment void rights' => [
- { rightname=>'Credit card void', desc=>'Enable local-only voiding of echeck payments in addition to refunds against the payment gateway.' }, #aka. cc-void
+ { rightname=>'Credit card void', desc=>'Enable local-only voiding of credit card payments in addition to refunds against the payment gateway.' }, #aka. cc-void
{ rightname=>'Echeck void', desc=>'Enable local-only voiding of echeck payments in addition to refunds against the payment gateway.' }, #aka. echeck-void
'Void payments',
{ rightname=>'Unvoid payments', desc=>'Enable unvoiding of voided payments' }, #aka. unvoid
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index db50d4250..2aeecc1b2 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -2801,13 +2801,16 @@ sub myaccount_passwd {
} )
or return { 'error' => "Service not found" };
- if ( exists($p->{'old_password'}) ) {
- return { 'error' => "Incorrect password." }
- unless $svc_acct->check_password($p->{'old_password'});
- }
+ my $error = '';
+
+ my $conf = new FS::Conf;
+ $error = 'Password too short.'
+ if length($p->{'new_password'}) < ($conf->config('passwordmin') || 6);
+ $error = 'Password too long.'
+ if length($p->{'new_password'}) > ($conf->config('passwordmax') || 8);
$svc_acct->set_password($p->{'new_password'});
- my $error = $svc_acct->replace();
+ $error ||= $svc_acct->replace();
my($label, $value) = $svc_acct->cust_svc->label;
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index eed84fc52..0eed8ee5d 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -1724,6 +1724,21 @@ and customer address. Include units.',
},
{
+ 'key' => 'sip_passwordmin',
+ 'section' => 'telephony',
+ 'description' => 'Minimum SIP password length (default 6)',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'sip_passwordmax',
+ 'section' => 'telephony',
+ 'description' => 'Maximum SIP password length (default 8) (don\'t set this over 12 if you need to import or export crypt() passwords)',
+ 'type' => 'text',
+ },
+
+
+ {
'key' => 'password-noampersand',
'section' => 'password',
'description' => 'Disallow ampersands in passwords',
@@ -2040,6 +2055,13 @@ and customer address. Include units.',
},
{
+ 'key' => 'show_ship_company',
+ 'section' => 'UI',
+ 'description' => 'Turns on display/collection of a "service company name" field for customers.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'show_ss',
'section' => 'UI',
'description' => 'Turns on display/collection of social security numbers in the web interface. Sometimes required by electronic check (ACH) processors.',
@@ -4745,6 +4767,17 @@ and customer address. Include units.',
},
{
+ 'key' => 'svc_phone-radius-password',
+ 'section' => 'telephony',
+ 'description' => 'Password when exporting svc_phone records to RADIUS',
+ 'type' => 'select',
+ 'select_hash' => [
+ '' => 'Use default from svc_phone-radius-default_password config',
+ 'countrycode_phonenum' => 'Phone number (with country code)',
+ ],
+ },
+
+ {
'key' => 'svc_phone-radius-default_password',
'section' => 'telephony',
'description' => 'Default password when exporting svc_phone records to RADIUS',
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 1a88c3acd..493734729 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -42,6 +42,7 @@ our $me = '[FS::Record]';
our $nowarn_identical = 0;
our $nowarn_classload = 0;
our $no_update_diff = 0;
+our $no_history = 0;
our $no_check_foreign = 1; #well, not inefficiently in perl by default anymore
@@ -1250,7 +1251,7 @@ sub insert {
}
my $h_sth;
- if ( defined dbdef->table('h_'. $table) ) {
+ if ( defined( dbdef->table('h_'. $table) ) && ! $no_history ) {
my $h_statement = $self->_h_statement('insert');
warn "[debug]$me $h_statement\n" if $DEBUG > 2;
$h_sth = dbh->prepare($h_statement) or do {
@@ -3003,7 +3004,7 @@ You should generally not have to worry about calling this, as the system handles
sub encrypt {
my ($self, $value) = @_;
- my $encrypted;
+ my $encrypted = $value;
if ($conf->exists('encryption')) {
if ($self->is_encrypted($value)) {
diff --git a/FS/FS/Report/Table.pm b/FS/FS/Report/Table.pm
index 1d60b6420..da4916176 100644
--- a/FS/FS/Report/Table.pm
+++ b/FS/FS/Report/Table.pm
@@ -757,7 +757,7 @@ sub with_cust_classnum {
return 'cust_main.classnum in('. join(',',@$classnums) .')'
if @$classnums;
}
- '';
+ ();
}
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 8ba60200e..bc9d37aed 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -3,7 +3,7 @@ package FS::Schema;
use vars qw(@ISA @EXPORT_OK $DEBUG $setup_hack %dbdef_cache);
use subs qw(reload_dbdef);
use Exporter;
-use DBIx::DBSchema 0.43; #0.43 for foreign keys
+use DBIx::DBSchema 0.44; #for foreign keys with MATCH / ON DELETE/UPDATE
use DBIx::DBSchema::Table;
use DBIx::DBSchema::Column;
use DBIx::DBSchema::Index;
@@ -1138,9 +1138,10 @@ sub tables_hashref {
{ columns => [ 'invnum' ],
table => 'cust_bill_void',
},
- { columns => [ 'pkgnum' ],
- table => 'cust_pkg',
- },
+ #pkgnum 0 and -1 are used for special things
+ #{ columns => [ 'pkgnum' ],
+ # table => 'cust_pkg',
+ #},
{ columns => [ 'pkgpart_override' ],
table => 'part_pkg',
references => [ 'pkgpart' ],
@@ -2389,7 +2390,7 @@ sub tables_hashref {
'index' => [ [ 'billpaynum' ], [ 'billpkgnum' ], ],
'foreign_keys' => [
{ columns => [ 'billpaynum' ],
- table => 'cust_bill_pay_batch',
+ table => 'cust_bill_pay',
},
{ columns => [ 'billpkgnum' ],
table => 'cust_bill_pkg',
@@ -3953,6 +3954,7 @@ sub tables_hashref {
'foreign_keys' => [
{ columns => [ 'jobnum' ],
table => 'queue',
+ on_delete => 'CASCADE',
},
],
},
@@ -3973,6 +3975,7 @@ sub tables_hashref {
{ columns => [ 'depend_jobnum' ],
table => 'queue',
references => [ 'jobnum' ],
+ on_delete => 'CASCADE',
},
],
},
@@ -4903,7 +4906,7 @@ sub tables_hashref {
#currently only u4:
# terminating number (as opposed to dialed destination)
- 'dst_term', 'varchar', '', $char_d, \"''", '',
+ 'dst_term', 'varchar', 'NULL', $char_d, '', '',
#these don't seem to be logged by most of the SQL cdr_* modules
#except tds under sql-illegal names, so;
@@ -5843,7 +5846,7 @@ sub tables_hashref {
'statustext', 'varchar', 'NULL', $char_d, '', '',
],
'primary_key' => 'upgradenum',
- 'unique' => [ [ 'upgradenum' ] ],
+ 'unique' => [],
'index' => [ [ 'upgrade' ] ],
},
diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm
index 840df7558..2314c02c1 100644
--- a/FS/FS/Template_Mixin.pm
+++ b/FS/FS/Template_Mixin.pm
@@ -581,11 +581,14 @@ sub print_generic {
my $countrydefault = $conf->config('countrydefault') || 'US';
foreach ( qw( address1 address2 city state zip country fax) ){
my $method = 'ship_'.$_;
- $invoice_data{"ship_$_"} = _latex_escape($cust_main->$method);
+ $invoice_data{"ship_$_"} = $escape_function->($cust_main->$method);
}
- foreach ( qw( contact company ) ) { #compatibility
- $invoice_data{"ship_$_"} = _latex_escape($cust_main->$_);
+ if ( length($cust_main->ship_company) ) {
+ $invoice_data{'ship_company'} = $escape_function->($cust_main->ship_company);
+ } else {
+ $invoice_data{'ship_company'} = $escape_function->($cust_main->company);
}
+ $invoice_data{'ship_contact'} = $escape_function->($cust_main->contact);
$invoice_data{'ship_country'} = ''
if ( $invoice_data{'ship_country'} eq $countrydefault );
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index d7f998bdf..e31ff14a5 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -323,6 +323,14 @@ sub cust_header {
@cust_header;
}
+sub cust_sort_fields {
+ cust_header(@_);
+ #inefficientish, but tiny lists and only run once per page
+
+ map { $_ eq 'custnum' ? 'custnum' : '' } @cust_fields;
+
+}
+
=item cust_sql_fields [ CUST_FIELDS_VALUE ]
Returns a list of fields for the SELECT portion of an SQL query.
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index b16cb8648..bf508dd8c 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -904,7 +904,7 @@ sub rate_prefix {
#${$opt{region_group_included_min}} -= $minutes
# if $region_group && $rate_detail->region_group;
- if ( $included_min->{$regionnum}{$ratetimenum} > $minutes ) {
+ if ( $included_min->{$regionnum}{$ratetimenum} >= $minutes ) {
$charge_sec = 0;
$included_min->{$regionnum}{$ratetimenum} -= $minutes;
} else {
diff --git a/FS/FS/contact_phone.pm b/FS/FS/contact_phone.pm
index 0eb216668..610753fc0 100644
--- a/FS/FS/contact_phone.pm
+++ b/FS/FS/contact_phone.pm
@@ -4,6 +4,7 @@ use base qw( FS::Record );
use strict;
use FS::Record qw( qsearch qsearchs );
use FS::contact;
+use FS::phone_type;
=head1 NAME
@@ -144,6 +145,16 @@ sub contact {
qsearchs( 'contact', { 'contactnum' => $self->contactnum } );
}
+sub phone_type {
+ my $self = shift;
+ qsearchs('phone_type', { 'phonetypenum' => $self->phonetypenum } );
+}
+
+sub typename {
+ my $self = shift;
+ $self->phone_type->typename;
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 4e34ef47b..d0e7048b7 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -1970,14 +1970,15 @@ sub print_csv {
my $time = $opt{'time'} || time;
+ my $tracctnum = ''; #leaking out from billco-specific sections :/
if ( $format eq 'billco' ) {
my $account_num =
$self->conf->config('billco-account_num', $cust_main->agentnum);
- my $tracctnum = $account_num eq 'display_custnum'
- ? $cust_main->display_custnum
- : $opt{'tracctnum'};
+ $tracctnum = $account_num eq 'display_custnum'
+ ? $cust_main->display_custnum
+ : $opt{'tracctnum'};
my $taxtotal = 0;
$taxtotal += $_->{'amount'} foreach $self->_items_tax;
@@ -2232,7 +2233,7 @@ sub print_csv {
$csv->combine(
'', # 1 | N/A-Leave Empty CHAR 2
'', # 2 | N/A-Leave Empty CHAR 15
- $opt{'tracctnum'}, # 3 | Account Number CHAR 15
+ $tracctnum, # 3 | Account Number CHAR 15
$self->invnum, # 4 | Invoice Number CHAR 15
$lineseq++, # 5 | Line Sequence (sort order) NUM 6
$item->{'description'}, # 6 | Transaction Detail CHAR 100
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index d768f8406..5126fea6b 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -1662,7 +1662,7 @@ sub queue_fuzzyfiles_update {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- foreach my $field ( 'first', 'last', 'company' ) {
+ foreach my $field ( 'first', 'last', 'company', 'ship_company' ) {
my $queue = new FS::queue {
'job' => 'FS::cust_main::Search::append_fuzzyfiles_fuzzyfield'
};
@@ -1724,6 +1724,7 @@ sub check {
|| $self->ut_snumbern('spouse_birthdate')
|| $self->ut_snumbern('anniversary_date')
|| $self->ut_textn('company')
+ || $self->ut_textn('ship_company')
|| $self->ut_anything('comments')
|| $self->ut_numbern('referral_custnum')
|| $self->ut_textn('stateid')
@@ -1741,11 +1742,13 @@ sub check {
|| $self->ut_currencyn('currency')
;
- my $company = $self->company;
- $company =~ s/^\s+//;
- $company =~ s/\s+$//;
- $company =~ s/\s+/ /g;
- $self->company($company);
+ foreach (qw(company ship_company)) {
+ my $company = $self->get($_);
+ $company =~ s/^\s+//;
+ $company =~ s/\s+$//;
+ $company =~ s/\s+/ /g;
+ $self->set($_, $company);
+ }
#barf. need message catalogs. i18n. etc.
$error .= "Please select an advertising source."
diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm
index 16db71271..b1438619b 100644
--- a/FS/FS/cust_main/Search.pm
+++ b/FS/FS/cust_main/Search.pm
@@ -21,6 +21,7 @@ $me = '[FS::cust_main::Search]';
@fuzzyfields = (
'cust_main.first', 'cust_main.last', 'cust_main.company',
+ 'cust_main.ship_company', # if you're using it
'cust_location.address1',
'contact.first', 'contact.last',
);
@@ -321,6 +322,7 @@ sub smart_search {
$sql .= " ( LOWER(cust_main.first) = $q_value
OR LOWER(cust_main.last) = $q_value
OR LOWER(cust_main.company) = $q_value
+ OR LOWER(cust_main.ship_company) = $q_value
";
#address1 (yes, it's a kludge)
@@ -356,27 +358,30 @@ sub smart_search {
#substring
- my @hashrefs = (
+ my @company_hashrefs = (
{ 'company' => { op=>'ILIKE', value=>"%$value%" }, },
+ { 'ship_company' => { op=>'ILIKE', value=>"%$value%" }, },
);
+ my @hashrefs = ();
+
if ( $first && $last ) {
- push @hashrefs,
+ @hashrefs = (
{ 'first' => { op=>'ILIKE', value=>"%$first%" },
'last' => { op=>'ILIKE', value=>"%$last%" },
},
- ;
+ );
} else {
- push @hashrefs,
+ @hashrefs = (
{ 'first' => { op=>'ILIKE', value=>"%$value%" }, },
{ 'last' => { op=>'ILIKE', value=>"%$value%" }, },
- ;
+ );
}
- foreach my $hashref ( @hashrefs ) {
+ foreach my $hashref ( @company_hashrefs, @hashrefs ) {
push @cust_main, qsearch( {
'table' => 'cust_main',
@@ -402,8 +407,6 @@ sub smart_search {
#contact substring
- shift @hashrefs; #no company column in contact table
-
foreach my $hashref ( @hashrefs ) {
push @cust_main,
@@ -439,7 +442,7 @@ sub smart_search {
%fuzopts
);
}
- foreach my $field ( 'first', 'last', 'company' ) {
+ foreach my $field ( 'first', 'last', 'company', 'ship_company' ) {
push @cust_main, FS::cust_main::Search->fuzzy_search(
{ $field => $value },
%fuzopts
@@ -1193,6 +1196,7 @@ sub append_fuzzyfiles {
#foreach my $fuzzy (@fuzzyfields) {
foreach my $fuzzy ( 'cust_main.first', 'cust_main.last', 'cust_main.company',
'cust_location.address1',
+ 'cust_main.ship_company',
) {
append_fuzzyfiles_fuzzyfield($fuzzy, shift);
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index 0669e1aa9..a7b91083f 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -36,6 +36,7 @@ FS::UID->install_callback( sub {
} );
@encrypted_fields = ('payinfo');
+sub nohistory_fields { ('payinfo'); }
=head1 NAME
diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm
index b93d8166d..db53b19c9 100644
--- a/FS/FS/cust_pay_batch.pm
+++ b/FS/FS/cust_pay_batch.pm
@@ -16,6 +16,9 @@ use FS::cust_bill;
# 3 is even more information including possibly sensitive data
$DEBUG = 0;
+#@encrypted_fields = ('payinfo');
+sub nohistory_fields { ('payinfo'); }
+
=head1 NAME
FS::cust_pay_batch - Object methods for batch cards
diff --git a/FS/FS/cust_pay_pending.pm b/FS/FS/cust_pay_pending.pm
index 8c6ef69ae..572a2ade2 100644
--- a/FS/FS/cust_pay_pending.pm
+++ b/FS/FS/cust_pay_pending.pm
@@ -12,6 +12,7 @@ use FS::cust_pay;
@ISA = qw( FS::payinfo_transaction_Mixin FS::cust_main_Mixin FS::Record );
@encrypted_fields = ('payinfo');
+sub nohistory_fields { ('payinfo'); }
=head1 NAME
diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm
index 92a96cb96..c42dc18e0 100644
--- a/FS/FS/cust_pay_void.pm
+++ b/FS/FS/cust_pay_void.pm
@@ -16,6 +16,8 @@ use FS::cust_pay;
use FS::cust_pkg;
@encrypted_fields = ('payinfo');
+sub nohistory_fields { ('payinfo'); }
+
$otaker_upgrade_kludge = 0;
=head1 NAME
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index 5abdbe2ee..8d12ab9c7 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -1859,7 +1859,7 @@ sub change {
if ( $opt->{cust_main} ) {
my $cust_main = $opt->{cust_main};
unless ( $cust_main->custnum ) {
- my $error = $cust_main->insert;
+ my $error = $cust_main->insert( @{ $opt->{cust_main_insert_args}||[] } );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "inserting cust_main (transaction rolled back): $error";
@@ -3461,8 +3461,7 @@ sub attribute_since_sqlradacct {
foreach my $cust_svc (
grep {
my $part_svc = $_->part_svc;
- $part_svc->svcdb eq 'svc_acct'
- && scalar($part_svc->part_export_usage);
+ scalar($part_svc->part_export_usage);
} $self->cust_svc
) {
$sum += $cust_svc->attribute_since_sqlradacct($start, $end, $attrib);
diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index 064992955..d29db5cfa 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -13,6 +13,7 @@ use FS::cust_pay_refund;
use FS::cust_main;
@encrypted_fields = ('payinfo');
+sub nohistory_fields { ('payinfo'); }
=head1 NAME
diff --git a/FS/FS/part_event/Action/letter.pm b/FS/FS/part_event/Action/letter.pm
index 57b7b7783..835dec2b9 100644
--- a/FS/FS/part_event/Action/letter.pm
+++ b/FS/FS/part_event/Action/letter.pm
@@ -20,6 +20,7 @@ sub option_fields {
'type' => 'select-table',
'table' => 'msg_template',
'name_col' => 'msgname',
+ 'hashref' => { disabled => '' },
'disable_empty' => 1,
},
);
diff --git a/FS/FS/part_event/Action/notice.pm b/FS/FS/part_event/Action/notice.pm
index 8e22c6844..7c8ed1682 100644
--- a/FS/FS/part_event/Action/notice.pm
+++ b/FS/FS/part_event/Action/notice.pm
@@ -19,6 +19,7 @@ sub option_fields {
'msgnum' => { 'label' => 'Template',
'type' => 'select-table',
'table' => 'msg_template',
+ 'hashref' => { disabled => '' },
'name_col' => 'msgname',
'disable_empty' => 1,
},
diff --git a/FS/FS/part_event/Action/notice_to.pm b/FS/FS/part_event/Action/notice_to.pm
index 194aeb84f..d300e3385 100644
--- a/FS/FS/part_event/Action/notice_to.pm
+++ b/FS/FS/part_event/Action/notice_to.pm
@@ -24,6 +24,7 @@ sub option_fields {
'type' => 'select-table',
'table' => 'msg_template',
'name_col' => 'msgname',
+ 'hashref' => { disabled => '' },
'disable_empty' => 1,
},
);
diff --git a/FS/FS/part_event/Action/svc_acct_notice.pm b/FS/FS/part_event/Action/svc_acct_notice.pm
index d71a1371a..97a4ad686 100644
--- a/FS/FS/part_event/Action/svc_acct_notice.pm
+++ b/FS/FS/part_event/Action/svc_acct_notice.pm
@@ -18,6 +18,7 @@ sub option_fields {
'type' => 'select-table',
'table' => 'msg_template',
'name_col' => 'msgname',
+ 'hashref' => { disabled => '' },
'disable_empty' => 1,
},
);
diff --git a/FS/FS/part_export/rt_ticket.pm b/FS/FS/part_export/rt_ticket.pm
index 7ae6105a0..72e387c56 100644
--- a/FS/FS/part_export/rt_ticket.pm
+++ b/FS/FS/part_export/rt_ticket.pm
@@ -21,7 +21,7 @@ my %template_select = (
%templates = (0 => '',
map { $_->msgnum, $_->msgname }
qsearch({ table => 'msg_template',
- hashref => {},
+ hashref => { disabled => '' },
order_by => 'ORDER BY msgnum ASC'
})
);
diff --git a/FS/FS/part_export/send_email.pm b/FS/FS/part_export/send_email.pm
index 6ba131f18..1fcb828b7 100644
--- a/FS/FS/part_export/send_email.pm
+++ b/FS/FS/part_export/send_email.pm
@@ -21,7 +21,7 @@ my %template_select = (
%templates = (0 => '',
map { $_->msgnum, $_->msgname }
qsearch({ table => 'msg_template',
- hashref => {},
+ hashref => { disabled => 1 },
order_by => 'ORDER BY msgnum ASC'
})
);
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
index ce1369510..f7e86514b 100644
--- a/FS/FS/part_export/shellcommands.pm
+++ b/FS/FS/part_export/shellcommands.pm
@@ -267,17 +267,19 @@ sub export_pkg_change {
my @fields = qw( pkgnum pkgpart agent_pkgid ); #others?
my @date_fields = qw( order_date start_date setup bill last_bill susp adjourn
- resume cancel uncancel expore contract_end );
+ resume cancel uncancel expire contract_end );
no strict 'vars';
{
no strict 'refs';
foreach (@fields) {
- ${"old_$_"} = $old_cust_pkg->getfield($_);
+ ${"old_$_"} = $old_cust_pkg ? $old_cust_pkg->getfield($_) : '';
${"new_$_"} = $new_cust_pkg->getfield($_);
}
foreach (@date_fields) {
- ${"old_$_"} = time2str('%Y-%m-%d', $old_cust_pkg->getfield($_));
+ ${"old_$_"} = $old_cust_pkg
+ ? time2str('%Y-%m-%d', $old_cust_pkg->getfield($_))
+ : '';
${"new_$_"} = time2str('%Y-%m-%d', $new_cust_pkg->getfield($_));
}
}
diff --git a/FS/FS/part_pkg/bulk_Common.pm b/FS/FS/part_pkg/bulk_Common.pm
index 26550df70..4e8850ee5 100644
--- a/FS/FS/part_pkg/bulk_Common.pm
+++ b/FS/FS/part_pkg/bulk_Common.pm
@@ -47,7 +47,7 @@ sub price_info {
#some false laziness-ish w/agent.pm... not a lot
sub calc_recur {
- my($self, $cust_pkg, $sdate, $details ) = @_;
+ my($self, $cust_pkg, $sdate, $details, $param ) = @_;
my $conf = new FS::Conf;
my $money_char = $conf->config('money_char') || '$';
@@ -106,10 +106,13 @@ sub calc_recur {
}
}
- sprintf('%.2f', $self->base_recur($cust_pkg, $sdate) + $total_svc_charge );
-}
+ my $charge = $self->base_recur($cust_pkg, $sdate) + $total_svc_charge;
+
+ $param->{'override_charges'} = $total_svc_charge / $self->freq;
+ my $discount = $self->calc_discount($cust_pkg, $sdate, $details, $param);
-sub can_discount { 0; }
+ sprintf('%.2f', $charge - $discount );
+}
sub hide_svc_detail { 1; }
diff --git a/FS/FS/queue.pm b/FS/FS/queue.pm
index 3f8763da8..8ebadd417 100644
--- a/FS/FS/queue.pm
+++ b/FS/FS/queue.pm
@@ -193,20 +193,6 @@ deleted as well
sub delete {
my $self = 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 @del = qsearch( 'queue_arg', { 'jobnum' => $self->jobnum } );
- push @del, qsearch( 'queue_depend', { 'depend_jobnum' => $self->jobnum } );
-
my $reportname = '';
if ( $self->status =~/^done/ ) {
my $dropstring = rooturl(). '/misc/queued_report\?report=';
@@ -216,20 +202,7 @@ sub delete {
}
my $error = $self->SUPER::delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- foreach my $del ( @del ) {
- $error = $del->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return $error if $error;
unlink $reportname if $reportname;
diff --git a/FS/FS/svc_MAC_Mixin.pm b/FS/FS/svc_MAC_Mixin.pm
new file mode 100644
index 000000000..737a8e83f
--- /dev/null
+++ b/FS/FS/svc_MAC_Mixin.pm
@@ -0,0 +1,65 @@
+package FS::svc_MAC_Mixin;
+
+use strict;
+#use FS::Record qw(qsearch);
+#use FS::Conf;
+# careful about importing anything here--it will end up in a LOT of
+# namespaces
+
+#use vars qw(@subclasses $DEBUG $conf);
+
+#$DEBUG = 0;
+
+# any subclass that can have MAC addresses needs to be added here
+#@subclasses = (qw(FS::svc_broadband FS::svc_cable));
+
+#sub conf {
+# $conf ||= FS::Conf->new;
+#}
+
+=head1 NAME
+
+FS::MAC_Mixin - Mixin class for objects that have MAC addresses assigned.
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=head1 METHODS
+
+=over 4
+
+=item mac_addr_pretty
+
+=cut
+
+sub mac_addr_pretty {
+ my $self = shift;
+ $self->mac_addr_formatted('U',':');
+}
+
+=item mac_addr_formatted CASE DELIMITER
+
+Format the MAC address (for use by exports). If CASE starts with "l"
+(for "lowercase"), it's returned in lowercase. DELIMITER is inserted
+between octets.
+
+=cut
+
+sub mac_addr_formatted {
+ my $self = shift;
+ my ($case, $delim) = @_;
+ my $addr = $self->mac_addr;
+ $addr = lc($addr) if $case =~ /^l/i;
+ join( $delim || '', $addr =~ /../g );
+}
+
+=back
+
+=head1 BUGS
+
+=cut
+
+1;
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
index 6073902e8..b9c89cef7 100755
--- a/FS/FS/svc_broadband.pm
+++ b/FS/FS/svc_broadband.pm
@@ -3,6 +3,7 @@ use base qw(
FS::svc_Radius_Mixin
FS::svc_Tower_Mixin
FS::svc_IP_Mixin
+ FS::svc_MAC_Mixin
FS::svc_Common
);
@@ -262,7 +263,7 @@ sub smart_search {
=item label
-Returns the IP address.
+Returns the IP address, MAC address and description.
=cut
@@ -419,22 +420,6 @@ sub _check_duplicate {
'';
}
-=item mac_addr_formatted CASE DELIMITER
-
-Format the MAC address (for use by exports). If CASE starts with "l"
-(for "lowercase"), it's returned in lowercase. DELIMITER is inserted
-between octets.
-
-=cut
-
-sub mac_addr_formatted {
- my $self = shift;
- my ($case, $delim) = @_;
- my $addr = $self->mac_addr;
- $addr = lc($addr) if $case =~ /^l/i;
- join( $delim || '', $addr =~ /../g );
-}
-
#class method
sub _upgrade_data {
my $class = shift;
diff --git a/FS/FS/svc_cable.pm b/FS/FS/svc_cable.pm
index 672a34d7b..5d281135b 100644
--- a/FS/FS/svc_cable.pm
+++ b/FS/FS/svc_cable.pm
@@ -1,5 +1,7 @@
package FS::svc_cable;
-use base qw( FS::svc_Common ); #qw( FS::device_Common FS::svc_Common );
+use base qw( FS::svc_MAC_Mixin
+ FS::svc_Common
+ ); #FS::device_Common
use strict;
use Tie::IxHash;
@@ -115,6 +117,22 @@ sub table_info {
};
}
+=item label
+
+Returns the MAC address and serial number.
+
+=cut
+
+sub label {
+ my $self = shift;
+ my @label = ();
+ push @label, 'MAC:'. $self->mac_addr_pretty
+ if $self->mac_addr;
+ push @label, 'Serial#'. $self->serialnum
+ if $self->serialnum;
+ return join(', ', @label);
+}
+
=item insert
Adds this record to the database. If there is an error, returns the error,
diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm
index 77b013726..887f7bed3 100644
--- a/FS/FS/svc_phone.pm
+++ b/FS/FS/svc_phone.pm
@@ -2,9 +2,12 @@ package FS::svc_phone;
use strict;
use base qw( FS::svc_Domain_Mixin FS::location_Mixin FS::svc_Common );
-use vars qw( $DEBUG $me @pw_set $conf $phone_name_max );
+use vars qw( $DEBUG $me @pw_set $conf $phone_name_max
+ $passwordmin $passwordmax
+ );
use Data::Dumper;
use Scalar::Util qw( blessed );
+use List::Util qw( min );
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
use FS::PagedSearch qw( psearch );
@@ -26,6 +29,8 @@ $DEBUG = 0;
FS::UID->install_callback( sub {
$conf = new FS::Conf;
$phone_name_max = $conf->config('svc_phone-phone_name-max_length');
+ $passwordmin = $conf->config('sip_passwordmin') || 0;
+ $passwordmax = $conf->config('sip_passwordmax') || 80;
}
);
@@ -534,10 +539,17 @@ sub check {
}
}
- unless ( length($self->sip_password) ) { # option for this?
+ if ( length($self->sip_password) ) {
+
+ return "SIP password must be longer than $passwordmin characters"
+ if length($self->sip_password) < $passwordmin;
+ return "SIP password must be shorter than $passwordmax characters"
+ if length($self->sip_password) > $passwordmax;
+
+ } else { # option for this?
$self->sip_password(
- join('', map $pw_set[ int(rand $#pw_set) ], (0..16) )
+ join('', map $pw_set[ int(rand $#pw_set) ], (1..min($passwordmax,16)) )
);
}
@@ -638,7 +650,13 @@ sub radius_check {
my $conf = new FS::Conf;
- $check{'User-Password'} = $conf->config('svc_phone-radius-default_password');
+ my $password;
+ if ( $conf->config('svc_phone-radius-password') eq 'countrycode_phonenum' ) {
+ $password = $self->countrycode. $self->phonenum;
+ } else {
+ $password = $conf->config('svc_phone-radius-default_password');
+ }
+ $check{'User-Password'} = $password;
%check;
}
diff --git a/FS/bin/freeside-queued b/FS/bin/freeside-queued
index 5eac06b24..f1a87cac9 100644
--- a/FS/bin/freeside-queued
+++ b/FS/bin/freeside-queued
@@ -12,6 +12,7 @@ use FS::Record qw(qsearch);
use FS::queue;
use FS::queue_depend;
use FS::Log;
+use FS::Cron::expire_user_pref qw( expire_user_pref );
# no autoloading for non-FS classes...
use Net::SSH 0.07;
@@ -66,6 +67,7 @@ while (1) {
if ( $kids >= $max_kids ) {
warn "WARNING: maximum $kids children reached\n" unless $warnkids++;
&reap_kids;
+ expire_user_pref() unless $warnkids % 10;
sleep 1; #waiting for signals is cheap
next;
}
@@ -131,6 +133,7 @@ while (1) {
undef $FS::UID::dbh;
next;
};
+ expire_user_pref();
sleep $sleep_time;
next;
}
diff --git a/FS/bin/freeside-upgrade b/FS/bin/freeside-upgrade
index 7cacf105c..45d2709da 100755
--- a/FS/bin/freeside-upgrade
+++ b/FS/bin/freeside-upgrade
@@ -84,6 +84,13 @@ if ( dbdef->table('areacode') and
}
}
+if ( dbdef->table('upgrade_journal') ) {
+ push @bugfix, "SELECT SETVAL( 'upgrade_journal_upgradenum_seq',
+ ( SELECT MAX(upgradenum) FROM upgrade_journal )
+ )
+ ";
+}
+
if ( $DRY_RUN ) {
print
join(";\n", @bugfix ). ";\n";
diff --git a/bin/restore-ship_company b/bin/restore-ship_company
new file mode 100644
index 000000000..cee700962
--- /dev/null
+++ b/bin/restore-ship_company
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+use FS::UID 'adminsuidsetup';
+use FS::Record qw(qsearch qsearchs dbh);
+use FS::cust_main;
+my $user = shift or die "Usage:
+ restore-ship_company username [ max-age ]
+";
+adminsuidsetup($user);
+
+$FS::UID::AutoCommit = 1;
+local $FS::cust_main::import = 1;
+
+my $days = shift || 30;
+my $time = time - (86400*$days); # by default, only restore within the last
+ # 30 days
+foreach my $cust_main (qsearch('cust_main', { ship_company => '' })) {
+ my $custnum = $cust_main->custnum;
+ my $last_h = qsearchs({
+ table => 'h_cust_main',
+ extra_sql => " WHERE custnum = $custnum".
+ " AND ship_company IS NOT NULL".
+ " AND history_date >= $time",
+ order_by => " ORDER BY history_date DESC LIMIT 1",
+ });
+ next if !$last_h;
+ print "$custnum\t".$last_h->ship_company."\n";
+ $cust_main->set('ship_company' => $last_h->ship_company);
+ my $error = $cust_main->replace;
+ warn "Error setting service company for customer #$custnum:\n $error\n"
+ if $error;
+}
diff --git a/bin/test_scrub b/bin/test_scrub
index 45a257ab9..e39a28a4e 100644
--- a/bin/test_scrub
+++ b/bin/test_scrub
@@ -3,6 +3,7 @@
#This drops anything from the database that could cause live things to happen.
#You'd want to do this on a test copy of your live database but NEVER on the
#live database itself.
+die "remove this line to run -- NEVER ON A LIVE DATABASE";
#-all exports (all records in part_export, part_export_option export_svc)
#-all non-POST invoice destinations (cust_main_invoice)
@@ -42,6 +43,17 @@ my $dsth = dbh->prepare("DELETE FROM cust_main_invoice WHERE dest != 'POST'")
or die dbh->errstr;
$dsth->execute or die $dsth->errstr;
+foreach my $table (qw( cust_main
+ cust_pay_pending cust_pay cust_pay_void cust_pay_batch
+ cust_refund
+)) {
+ my $ccsth = dbh->prepare("
+ UPDATE $table SET payinfo = '4111111111111111'
+ WHERE payby = 'CARD' OR payby = 'DCRD'
+ ") or die dbh->errstr;
+ $ccsth->execute or die $ccsth->errstr;
+}
+
my $sth = dbh->prepare("UPDATE part_event SET disabled = 'Y'");
$sth->execute or die $sth->errstr;
diff --git a/fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm b/fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm
index 0df24f7d7..6086717ec 100644
--- a/fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm
+++ b/fs_selfservice/FS-SelfService/SelfService/FreeRadiusVoip.pm
@@ -1,8 +1,13 @@
#Add this to the modules section of radiusd.conf
# perl {
# #path to this module
-# module=/usr/local/share/perl/5.8.8/FS/SelfService/FreeRadiusVoip.pm
+# # deb 6 example
+# #module=/usr/local/share/perl/5.10.1/FS/SelfService/FreeRadiusVoip.pm
+# # deb 7 example
+# module=/usr/local/share/perl/5.14.2/FS/SelfService/FreeRadiusVoip.pm
+#
# func_authorize = authorize;
+#
# }
#
#In the Authorize section
@@ -11,9 +16,9 @@
#
# #N/A# Add a line containing 'perl' to the Accounting section.
#
-# and on debian systems, add this to /etc/init.d/freeradius, with the
+# and on debian 6 systems, add this to /etc/init.d/freeradius, with the
# correct path (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=416266)
-# LD_PRELOAD=/usr/lib/libperl.so.5.8.8
+# LD_PRELOAD=/usr/lib/libperl.so.5.10
# export LD_PRELOAD
BEGIN { $FS::SelfService::skip_uid_check = 1; }
@@ -44,9 +49,13 @@ sub authorize {
if ( $response->{'error'} ) {
$RAD_REPLY{'Reply-Message'} = $response->{'error'};
return RLM_MODULE_REJECT;
- } else {
+ } elsif ( $response->{'seconds'} ) {
$RAD_REPLY{'Session-Timeout'} = $response->{'seconds'};
return RLM_MODULE_OK;
+ } else {
+ # if the called number is free, put 1 in the Termination-Action attribute
+ $RAD_REPLY{'Termination-Action'} = 1;
+ return RLM_MODULE_OK;
}
}
diff --git a/httemplate/browse/msg_template.html b/httemplate/browse/msg_template.html
index bb5ac94a0..ef0b2dafd 100644
--- a/httemplate/browse/msg_template.html
+++ b/httemplate/browse/msg_template.html
@@ -5,14 +5,15 @@
'query' => { 'table' => 'msg_template', },
'count_query' => 'SELECT COUNT(*) FROM msg_template',
'disableable' => 1,
- 'disabled_statuspos' => 2,
+ 'disabled_statuspos' => (scalar(@locales) + 3),
'agent_virt' => 1,
'agent_null_right' => ['View global templates','Edit global templates'],
'agent_pos' => 1,
- 'header' => [ 'Name', '', map '', @locales ],
- 'fields' => [ 'msgname', @locales ],
- 'links' => [ $link, @locale_links ],
- 'cell_style' => [ '', '', map $locale_style, @locales ],
+ 'header' => [ 'Name', '', map ('', @locales), '' ],
+ 'fields' => [ 'msgname', @locales, $disable_link_label ],
+ 'links' => [ $link, @locale_links, '' ],
+ 'link_onclicks' => [ '', map('', @locale_links), $disable_link ],
+ 'cell_style' => [ '', '', map ($locale_style, @locales), $locale_style ],
)
%>
<%init>
@@ -30,7 +31,7 @@ if ( $curuser->access_right(['Edit templates', 'Edit global templates']) ) {
my $link = [ "${p}edit/msg_template.html?msgnum=", 'msgnum' ];
-my $locale_style = 'font-size:0.8em; padding:3px; background-color:';
+my $locale_style = 'font-size:0.8em; padding:3px';
my (@locales, @locale_links);
foreach my $l ( FS::Locales->locales ) {
@@ -44,6 +45,20 @@ foreach my $l ( FS::Locales->locales ) {
[ "${p}edit/msg_template.html?locale=$l;msgnum=", 'msgnum' ];
};
}
-
+
+my $disable_link = sub {
+ my $template = shift;
+ include('/elements/popup_link_onclick.html',
+ action => $p.'misc/disable-msg_template.cgi?msgnum=' .
+ $template->msgnum .
+ ($template->disabled ? ';enable=1' : ''),
+ actionlabel => 'Disable lemplate',
+ );
+};
+
+my $disable_link_label = sub {
+ my $template = shift;
+ $template->disabled ? '(enable)' : '(disable)' ;
+};
</%init>
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index d597d0bc2..480047cae 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -73,6 +73,7 @@
><% mt('same as billing address') |h %>
<DIV CLASS="fsinnerbox">
<TABLE ID="table_ship_location" WIDTH="100%">
+ <& cust_main/before_ship_location.html, $cust_main &>
<& /elements/location.html,
object => $cust_main->ship_location,
prefix => 'ship_',
@@ -202,6 +203,7 @@ my $prospectnum = '';
my $locationnum = '';
my $same = '';
+$m->comp('/elements/handle_uri_query', 'secure'=>1);
if ( $cgi->param('error') ) {
diff --git a/httemplate/edit/cust_main/before_ship_location.html b/httemplate/edit/cust_main/before_ship_location.html
new file mode 100644
index 000000000..badb5e8cd
--- /dev/null
+++ b/httemplate/edit/cust_main/before_ship_location.html
@@ -0,0 +1,13 @@
+% if ( length($cust_main->ship_company) or
+% $conf->exists('show_ship_company') ) {
+ <& /elements/tr-input-text.html,
+ label => mt('Company'),
+ field => 'ship_company',
+ curr_value => $cust_main->ship_company,
+ colspan => 6,
+ &>
+% }
+<%init>
+my $cust_main = shift;
+my $conf = FS::Conf->new;
+</%init>
diff --git a/httemplate/edit/cust_main/contact.html b/httemplate/edit/cust_main/contact.html
index 4140ec1ea..c2ebb093c 100644
--- a/httemplate/edit/cust_main/contact.html
+++ b/httemplate/edit/cust_main/contact.html
@@ -94,30 +94,13 @@
</%def>
<%def phones>
- <TR>
- <TD ALIGN="right" VALIGN="top"><% mt('Phones') %></TD>
- <TD COLSPAN=6>
-
- <TABLE CELLSPACING=0 CELLPADDING=0>
- <TR>
- <TD>
- <INPUT TYPE="text" NAME="<%$pre%>daytime" VALUE="<% $cust_main->get($pre.'daytime') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- <BR><FONT SIZE=-1><% $daytime_label %></FONT>
- </TD>
- <TD>&nbsp;</TD>
- <TD>
- <INPUT TYPE="text" NAME="<%$pre%>night" VALUE="<% $cust_main->get($pre.'night') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- <BR><FONT SIZE=-1><% $night_label %></FONT>
- </TD>
- <TD>&nbsp;</TD>
- <TD>
- <INPUT TYPE="text" NAME="<%$pre%>mobile" VALUE="<% $cust_main->get($pre.'mobile') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- <BR><FONT SIZE=-1><% $mobile_label %></FONT>
- </TD>
- </TR>
- </TABLE>
- </TD>
- </TR>
+ <& /elements/tr-cust_main-phones.html,
+ 'prefix' => $pre,
+ 'cust_main' => $cust_main,
+ 'onchange' => $onchange,
+ 'disabled' => $disabled,
+ 'style' => $style,
+ &>
</%def>
<%def fax>
@@ -136,9 +119,7 @@ my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
</%once>
<%shared>
-my( %opt, $cust_main, $pre, $onchange, $disabled, @style, $style,
- $daytime_label, $night_label, $mobile_label,
- );
+my( %opt, $cust_main, $pre, $onchange, $disabled, @style, $style );
</%shared>
<%init>
@@ -176,16 +157,6 @@ $opt{geocode} ||= $cust_main->get('geocode');
$opt{censustract} ||= $cust_main->censustract;
-$daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
- ? 'Day'
- : FS::Msgcat::_gettext('daytime');
-$night_label = FS::Msgcat::_gettext('night') =~/^(night)?$/
- ? 'Night'
- : FS::Msgcat::_gettext('night') || 'Night';
-$mobile_label = FS::Msgcat::_gettext('mobile') =~/^(mobile)?$/
- ? 'Mobile'
- : FS::Msgcat::_gettext('mobile') || 'Mobile';
-
my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
? 'Driver&rsquo;s License'
: FS::Msgcat::_gettext('stateid') || 'Driver&rsquo;s License';
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index 6c965326b..9e27f2a4c 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -527,7 +527,7 @@ Example:
% if ( $f->{curr_value_callback} ) {
% $curr_value = &{ $f->{curr_value_callback} }( $cgi, $object, $field ),
% } else {
-% $curr_value = $object->$field();
+% $curr_value = $object->$field() if $field;
% }
% $curr_value = &{ $opt{'value_callback'} }( $f->{'field'}, $curr_value )
% if $opt{'value_callback'} && $mode ne 'error';
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
index ff8be1a71..4fb8f622d 100755
--- a/httemplate/edit/process/cust_main.cgi
+++ b/httemplate/edit/process/cust_main.cgi
@@ -1,7 +1,7 @@
% if ( $error ) {
% $cgi->param('error', $error);
-%
-<% $cgi->redirect(popurl(2). "cust_main.cgi?". $cgi->query_string ) %>
+% my $query = $m->scomp('/elements/create_uri_query', 'secure'=>1);
+<% $cgi->redirect(popurl(2). "cust_main.cgi?$query" ) %>
%
% } else {
%
diff --git a/httemplate/edit/process/detach-cust_pkg.html b/httemplate/edit/process/detach-cust_pkg.html
index ab87eb536..782ffa5e0 100644
--- a/httemplate/edit/process/detach-cust_pkg.html
+++ b/httemplate/edit/process/detach-cust_pkg.html
@@ -30,16 +30,23 @@ my $cust_location = new FS::cust_location {
map { $_ => scalar($cgi->param($_)) } FS::cust_main->location_fields
};
+#false laziness w/process/cust_main.cgi
+my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );
+push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST');
+push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');
+$cgi->param('invoicing_list', join(',', @invoicing_list) );
+
my $cust_main = new FS::cust_main {
( map { ( $_, scalar($cgi->param($_)) ) } fields('cust_main') ),
( map { ( "ship_$_", '' ) } FS::cust_main->location_fields ),
- 'bill_location' => $cust_location,
- 'ship_location' => $cust_location,
+ 'bill_location' => $cust_location,
+ 'ship_location' => $cust_location,
};
my $pkg_or_error = $cust_pkg->change( {
- 'keep_dates' => 1,
- 'cust_main' => $cust_main,
+ 'keep_dates' => 1,
+ 'cust_main' => $cust_main,
+ 'cust_main_insert_args' => [ {}, \@invoicing_list ],
} );
my $error = ref($pkg_or_error) ? '' : $pkg_or_error;
diff --git a/httemplate/elements/create_uri_query b/httemplate/elements/create_uri_query
index 32d8e2f87..ce6249e0e 100644
--- a/httemplate/elements/create_uri_query
+++ b/httemplate/elements/create_uri_query
@@ -1,17 +1,34 @@
<% $query %>\
<%init>
+my %opt = @_;
+
+if ( $opt{secure} ) {
+
+ foreach my $param (grep /pay(info\d?|cvv)$/, $cgi->param) {
+ my $value = $cgi->param($param);
+ next unless length($value);
+ my $encrypted = FS::Record->encrypt( $value );
+ $cgi->param($param, $encrypted);
+ }
+
+}
+
my $query = $cgi->query_string;
-if ( length($query) > 1920 ) { #stupid IE 2083 URL limit
+if ( length($query) > 1920 || $opt{secure} ) { #stupid IE 2083 URL limit
my $session = int(rand(4294967296)); #XXX
my $pref = new FS::access_user_pref({
'usernum' => $FS::CurrentUser::CurrentUser->usernum,
'prefname' => "redirect$session",
'prefvalue' => $query,
- 'expiration' => time + 3600, #1h? 1m?
+ 'expiration' => time + ( $opt{secure} ? 120 #2m?
+ : 3600 #1h?
+ ),
});
+ local($FS::Record::no_history) = 1;
+
my $pref_error = $pref->insert;
if ( $pref_error ) {
die "FATAL: couldn't even set redirect cookie: $pref_error".
diff --git a/httemplate/elements/handle_uri_query b/httemplate/elements/handle_uri_query
index eb7ea1ae1..2dea96a6d 100644
--- a/httemplate/elements/handle_uri_query
+++ b/httemplate/elements/handle_uri_query
@@ -1,8 +1,20 @@
<%init>
+
+my %opt = @_;
+
if ( $cgi->param('redirect') ) {
my $session = $cgi->param('redirect');
+
my $pref = $FS::CurrentUser::CurrentUser->option("redirect$session");
die "unknown redirect session $session\n" unless length($pref);
$cgi = new CGI($pref);
+
+ foreach my $param (grep /pay(info\d?|cvv)$/, $cgi->param) {
+ my $value = $cgi->param($param);
+ next unless length($value);
+ my $decrypted = FS::Record->decrypt( $value );
+ $cgi->param($param, $decrypted);
+ }
+
}
</%init>
diff --git a/httemplate/elements/pager.html b/httemplate/elements/pager.html
index a53300f53..d360e6478 100644
--- a/httemplate/elements/pager.html
+++ b/httemplate/elements/pager.html
@@ -1,13 +1,8 @@
-% my %opt = @_;
-% my $pager = '';
-%
% if ( $opt{'total'} != $opt{'num_rows'} && $opt{'maxrecords'} ) {
%
% unless ( $opt{'offset'} == 0 ) {
% $cgi->param('offset', $opt{'offset'} - $opt{'maxrecords'});
-
<A HREF="<% $cgi->self_url %>"><B><FONT SIZE="+1">Previous</FONT></B></A>
-
% }
%
% my $page = 0;
@@ -47,9 +42,17 @@
%
% unless ( $opt{'offset'} + $opt{'maxrecords'} > $opt{'total'} ) {
% $cgi->param('offset', $opt{'offset'} + $opt{'maxrecords'});
-
<A HREF="<% $cgi->self_url %>"><B><FONT SIZE="+1">Next</FONT></B></A>
-%
% }
%
+% $cgi->param('offset', $orig_offset); #so future $self_url invocations don't advance a page
+%
% }
+<%init>
+
+my %opt = @_;
+
+my $orig_offset = $opt{'offset'};
+
+</%init>
+
diff --git a/httemplate/elements/searchbar-cust_main.html b/httemplate/elements/searchbar-cust_main.html
index 9a98417c8..5bfef484a 100644
--- a/httemplate/elements/searchbar-cust_main.html
+++ b/httemplate/elements/searchbar-cust_main.html
@@ -1,6 +1,6 @@
% if ( $curuser->access_right('List customers') ) {
- <FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0">
+ <FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="POST" STYLE="margin:0">
<INPUT NAME="search_cust" TYPE="text" VALUE="<% $cust_label |n %>" STYLE="width:<%$width%>" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" CLASS="fstext"><BR>
<A HREF="<%$fsurl%>search/report_cust_main.html" CLASS="fslink" STYLE="font-size: 11px"><% mt('Advanced') |h %></A>
<INPUT TYPE="submit" VALUE="<% mt('Search customers') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px">
diff --git a/httemplate/elements/tr-censustract.html b/httemplate/elements/tr-censustract.html
new file mode 100644
index 000000000..bd014f11b
--- /dev/null
+++ b/httemplate/elements/tr-censustract.html
@@ -0,0 +1,23 @@
+% if ($censustract) {
+<TR>
+ <TD ALIGN="right"><% mt('Census tract') |h %></TD>
+ <TD COLSPAN=5>
+ <SPAN STYLE="background-color: #ffffff; border: 1px solid #ffffff"><% $censustract |h %></SPAN>
+ &nbsp;<% $censusyear |h %>
+ </TD>
+</TR>
+% }
+<%init>
+
+my $location = shift;
+my $conf = FS::Conf->new;
+my ($censustract, $censusyear);
+if ($location->censustract) {
+ $censustract = $location->censustract;
+ $censusyear = '('. ($location->censusyear || mt('unknown year')) . ')';
+} elsif ($conf->exists('cust_main-require_censustract')) {
+ $censustract = mt('unknown');
+ $censusyear = '';
+}
+
+</%init>
diff --git a/httemplate/elements/tr-cust_main-phones.html b/httemplate/elements/tr-cust_main-phones.html
new file mode 100644
index 000000000..accf8ac64
--- /dev/null
+++ b/httemplate/elements/tr-cust_main-phones.html
@@ -0,0 +1,45 @@
+ <TR>
+ <TD ALIGN="right" VALIGN="top"><% mt('Phones') %></TD>
+ <TD COLSPAN=6>
+
+ <TABLE CELLSPACING=0 CELLPADDING=0>
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="<%$pre%>daytime" VALUE="<% $cust_main->get($pre.'daytime') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
+ <BR><FONT SIZE=-1><% $daytime_label %></FONT>
+ </TD>
+ <TD>&nbsp;</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="<%$pre%>night" VALUE="<% $cust_main->get($pre.'night') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
+ <BR><FONT SIZE=-1><% $night_label %></FONT>
+ </TD>
+ <TD>&nbsp;</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="<%$pre%>mobile" VALUE="<% $cust_main->get($pre.'mobile') %>" SIZE=18 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
+ <BR><FONT SIZE=-1><% $mobile_label %></FONT>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+<%init>
+
+my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
+ ? 'Day'
+ : FS::Msgcat::_gettext('daytime');
+my $night_label = FS::Msgcat::_gettext('night') =~/^(night)?$/
+ ? 'Night'
+ : FS::Msgcat::_gettext('night') || 'Night';
+my $mobile_label = FS::Msgcat::_gettext('mobile') =~/^(mobile)?$/
+ ? 'Mobile'
+ : FS::Msgcat::_gettext('mobile') || 'Mobile';
+
+my %opt = @_;
+
+my $pre = $opt{'prefix'};
+my $cust_main = $opt{'cust_main'};
+my $onchange = $opt{'onchange'};
+my $disabled = $opt{'disabled'};
+my $style = $opt{'style'};
+
+</%init>
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
index e1fa825c1..4ed9cd48e 100644
--- a/httemplate/elements/tr-select-cust_location.html
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -31,6 +31,9 @@ Example:
else what.form.<%$_%>.value = '';
if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#dddddd';
% }
+ if(what.form.enter_censustract) {
+ what.form.enter_censustract.disabled = true;
+ }
}
function location_clear(what) {
@@ -38,6 +41,9 @@ Example:
var ftype = what.form.<%$_%>.tagName;
if( ftype == 'INPUT' ) what.form.<%$_%>.value = '';
% }
+ if(what.form.enter_censustract) {
+ what.form.enter_censustract.value = '';
+ }
% if ( $opt{'alt_format'} ) {
changeSelect(what.form.location_kind, '');
changeSelect(what.form.location_type, '');
@@ -51,6 +57,9 @@ Example:
var ftype = what.form.<%$_%>.tagName;
if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#ffffff';
% }
+ if(what.form.enter_censustract) {
+ what.form.enter_censustract.disabled = false;
+ }
% if ( $opt{'alt_format'} ) {
if ( what.form.location_type &&
what.form.location_type.options[what.form.location_type.selectedIndex].value ) {
diff --git a/httemplate/misc/detach_pkg.html b/httemplate/misc/detach_pkg.html
index 64b3e6e3f..366bbac3f 100755
--- a/httemplate/misc/detach_pkg.html
+++ b/httemplate/misc/detach_pkg.html
@@ -50,9 +50,26 @@
</TD>
</TR>
+% if ( $conf->config_bool('cust_main-require_phone') ) {
+% #XXX should be sticky on errors
+% my $ph_cust_main = FS::cust_main->new({});
+% foreach my $contact_phone ( $cust_contact->contact_phone ) {
+% my $t = $contact_phone->typename;
+% #countrycodes? interface doesn't parse/take em yet
+% $ph_cust_main->daytime( $contact_phone->phonenum ) if $t eq 'Work';
+% $ph_cust_main->night( $contact_phone->phonenum ) if $t eq 'Home';
+% $ph_cust_main->mobile( $contact_phone->phonenum ) if $t eq 'Mobile';
+% $ph_cust_main->fax( $contact_phone->phonenum ) if $t eq 'Fax';
+% }
+
+ <& /elements/tr-cust_main-phones.html,
+ 'cust_main' => $ph_cust_main,
+ &>
+% }
+
</TABLE>
-%#XXX payment info
+%#payment info
%#XXX should be sticky on errors...
<& /edit/cust_main/billing.html, FS::cust_main->new({}),
invoicing_list => [],
diff --git a/httemplate/misc/disable-msg_template.cgi b/httemplate/misc/disable-msg_template.cgi
new file mode 100644
index 000000000..1eb4d25e5
--- /dev/null
+++ b/httemplate/misc/disable-msg_template.cgi
@@ -0,0 +1,77 @@
+% if ( @error ) {
+<& /elements/errorpage-popup.html, @error &>
+% } else {
+<& /elements/header-popup.html, "Template ${actioned}" &>
+ <SCRIPT TYPE="text/javascript">
+ window.top.location.reload();
+ </SCRIPT>
+</BODY>
+</HTML>
+% }
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = FS::Conf->new;
+my @error;
+my $actioned;
+
+die "access denied"
+ unless $curuser->access_right([ 'Edit templates', 'Edit global templates' ]);
+
+my $msgnum = $cgi->param('msgnum');
+$msgnum =~ /^\d+$/ or die "bad msgnum '$msgnum'";
+my $msg_template = qsearchs({
+ table => 'msg_template',
+ hashref => { msgnum => $msgnum },
+ extra_sql => ' AND '.
+ $curuser->agentnums_sql(null_right => 'Edit global templates'),
+});
+die "unknown msgnum $msgnum" unless $msg_template;
+
+if ( $cgi->param('enable') ) {
+ $actioned = 'enabled';
+ $msg_template->set('disabled' => '');
+} else {
+ $actioned = 'disabled';
+ # make sure it's not in use anywhere
+ my @inuse;
+
+ # notice, letter, notice_to events (if they're enabled)
+ my @events = qsearch({
+ table => 'part_event_option',
+ addl_from => ' JOIN part_event USING (eventpart)',
+ hashref => {
+ optionname => 'msgnum',
+ optionvalue => $msgnum,
+ },
+ extra_sql => ' AND disabled IS NULL',
+ });
+ push @inuse, map {"Billing event #".$_->eventpart} @events;
+
+ # send_email and rt_ticket exports
+ my @exports = qsearch( 'part_export_option', {
+ optionname => { op => 'LIKE', value => '%_template' },
+ optionvalue => $msgnum,
+ });
+ push @inuse, map {"Export #".$_->exportnum} @exports;
+
+ # payment_receipt_msgnum, decline_msgnum, etc.
+ my @confs = qsearch( 'conf', {
+ name => { op => 'LIKE', value => '%_msgnum' },
+ value => $msgnum,
+ });
+ push @inuse, map {"Configuration setting ".$_->name} @confs;
+ # XXX pending queue jobs?
+ if (@inuse) {
+ @error = ("This template is in use. Check the following settings:",
+ @inuse);
+ }
+
+ # good to go
+ $msg_template->set(disabled => 'Y');
+}
+if (!@error) {
+ my $error = $msg_template->replace;
+ push @error, $error if $error;
+}
+</%init>
diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html
index ad67b8d7e..3b2ac3c5f 100644
--- a/httemplate/misc/email-customers.html
+++ b/httemplate/misc/email-customers.html
@@ -98,6 +98,7 @@ Template:
<% include('/elements/select-table.html',
'label' => 'Template:',
'table' => 'msg_template',
+ 'hashref' => { disabled => '' },
'name_col' => 'msgname',
'empty_label' => '(none)',
'onchange' => 'toggle(this)',
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index d86641de3..f87862a3d 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -49,8 +49,9 @@
@currency,
'invnum',
'_date',
- #'pay_amount',
- #'credit_amount',
+ '', #'pay_amount',
+ '', #'credit_amount',
+ FS::UI::Web::cust_sort_fields(),
],
'links' => [
@pkgnum_null,
diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html
index d65af669a..294b7babb 100644
--- a/httemplate/view/cust_main/contacts.html
+++ b/httemplate/view/cust_main/contacts.html
@@ -41,7 +41,14 @@
<TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->company |h %></TD>
</TR>
% }
-% } # if $this eq 'bill'
+% } elsif ( $this eq 'ship' ) {
+% if ( $cust_main->ship_company ) { # mostly obsolete these days...
+ <TR>
+ <TD ALIGN="right"><% mt('Company') |h %></TD>
+ <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->ship_company |h %></TD>
+ </TR>
+% }
+% }
% # now the actual address
<TR>
<TD ALIGN="right"><% mt('Address') |h %></TD>
@@ -84,6 +91,7 @@
$cust_main->agentnum,
&>
% }
+<& /elements/tr-censustract.html, $location &>
% if ( $this eq 'bill' ) {
% # billing contact phone numbers
diff --git a/httemplate/view/cust_main/locations.html b/httemplate/view/cust_main/locations.html
index 7eb52ca46..fdbbc396b 100755
--- a/httemplate/view/cust_main/locations.html
+++ b/httemplate/view/cust_main/locations.html
@@ -1,40 +1,60 @@
<STYLE>
-span.loclabel {
+div.loclabel {
+ display: inline-block;
padding-left: 4px;
padding-right: 4px;
background-color: #cccccc;
- border: 1px solid black
+ border: 1px solid black;
+ border-bottom: 0px;
+ border-radius: 4px 4px 0 0;
+}
+div.disabled {
+ font-style: italic;
+ color: #808080;
}
table.location {
width: 100%;
padding: 1px;
border-spacing: 0px;
}
+.location-head th {
+ padding-bottom: 0px;
+ padding-left: 0px;
+ border-bottom: 1px solid black;
+ vertical-align: bottom;
+ text-align: left;
+ width: 100%;
+}
</STYLE>
% foreach my $locationnum (@sorted) {
% my $packages = $packages_in{$locationnum};
% my $loc = $locations{$locationnum};
% next if $loc->disabled and scalar(@$packages) == 0;
<TABLE CLASS="grid location">
-<TR><TH COLSPAN=3 ALIGN="left" VALIGN="bottom"
-STYLE="padding-bottom: 0px;
- padding-left: 0px;
- border-bottom-style: solid;
- border-bottom-color: black;
- border-bottom-width: 1px;">
-<SPAN CLASS="loclabel">
-% if ( $loc->disabled ) {
-<FONT COLOR="#808080"><I>
+<TR CLASS="location-head">
+<TH COLSPAN=5>
+<DIV CLASS="<% $loc->disabled ? 'loclabel disabled' : 'loclabel' %>">
+<% $loc->location_label %>
+% if ( $loc->censustract ) {
+ <BR>
+ <FONT SIZE=-1>
+ <% $loc->censustract %> (<% $loc->censusyear %> census)
+ </FONT>
+% } elsif ( $conf->exists('cust_main-require_censustract') ) {
+ <BR>
+ <FONT SIZE=-1 COLOR="#ee3300">
+ <% emt('Census tract unknown') %>
+ </FONT>
% }
-<% $loc->location_label %></SPAN>
-<SPAN STYLE="float:right;">
+</DIV>
+<DIV STYLE="display: inline; float:right;">
% if ( $locationnum && !$loc->disabled && ! $opt{no_links} ) {
<% edit_location_link($locationnum) %>
% }
% if ( $locationnum && !$loc->disabled && !$active{$locationnum} && ! $opt{no_links} ) {
&nbsp;<% disable_location_link($locationnum) %>
% }
-</SPAN></TH></TR>
+</DIV></TH></TR>
% if (@$packages) {
<& packages/section.html,
'packages' => $packages,
@@ -48,6 +68,7 @@ STYLE="padding-bottom: 0px;
my %opt = @_;
my $cust_main = $opt{'cust_main'};
my $all_packages = $opt{'packages'};
+my $conf = FS::Conf->new;
my %locations = map { $_->locationnum => $_ } qsearch({
'table' => 'cust_location',
diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html
index 5311aa5ae..7915195b4 100644
--- a/httemplate/view/cust_main/misc.html
+++ b/httemplate/view/cust_main/misc.html
@@ -171,17 +171,6 @@
% }
-% if ( $conf->exists('cust_main-require_censustract') ) {
-
- <TR>
- <TD ALIGN="right">
- <% mt('Census tract ([_1])', $cust_main->ship_location->censusyear) |h %>
- </TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->ship_location->censustract %></TD>
- </TR>
-
-% }
-
% if ( $cust_main->district ) {
<TR>
diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html
index 5ff2b1e1f..db67d45b9 100644
--- a/httemplate/view/cust_main/packages/location.html
+++ b/httemplate/view/cust_main/packages/location.html
@@ -1,35 +1,49 @@
% if ( $cust_pkg->change_from_pkg
-% and $cust_pkg->change_from_pkg->locationnum == $cust_pkg->locationnum )
+% and $cust_pkg->change_from_pkg->locationnum == $cust_pkg->locationnum)
% {
% # don't show the location
% } else {
-% if ( $default ) {
- <DIV STYLE="font-style: italic; font-size: small">
-% }
+% if ( !$conf->exists('cust_pkg-group_by_location') ) {
+% if ( $default ) {
+ <DIV STYLE="font-style: italic; font-size: small">
+% }
- <% $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,
- $opt{'cust_main'}->agentnum,
- &>
- </FONT>
-% }
+% 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,
+ $opt{'cust_main'}->agentnum,
+ &>
+ </FONT>
+% }
+% if ( $loc->censustract ) {
+ <BR>
+ <FONT SIZE=-1>
+ <% $loc->censustract %> (<% $loc->censusyear %> census)
+ </FONT>
+% } elsif ( $conf->exists('cust_main-require_censustract') ) {
+ <BR>
+ <FONT SIZE=-1 COLOR="#ee3300">
+ <% emt('Census tract unknown') %>
+ </FONT>
+% }
-% if ( $default ) {
- </DIV>
-% }
+% if ( $default ) {
+ </DIV>
+% }
+% } # all of this is hidden if packages are grouped by location, because
+% # it's in the top banner
% if ( ! $cust_pkg->get('cancel')
% && $FS::CurrentUser::CurrentUser->access_right('Change customer package')
@@ -41,11 +55,13 @@
(&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
% }
% if ( $cust_pkg->locationnum && ! $opt{no_links} ) {
- (&nbsp;<%edit_location_link($cust_pkg->locationnum)%>&nbsp;)
+ (&nbsp;<%pkg_edit_location_link($cust_pkg->locationnum)%>&nbsp;)
% }
</FONT>
% }
-% }
+% } # if the package is a scheduled future package change without location
+% # change, then don't show any of this at all. It's all implied by the
+% # preceding package.
<%init>
my $conf = new FS::Conf;
@@ -75,7 +91,7 @@ sub pkg_change_location_link {
);
}
-sub edit_location_link {
+sub pkg_edit_location_link {
my $locationnum = shift;
include( '/elements/popup_link.html',
'action' => $p. "edit/cust_location.cgi?locationnum=$locationnum",