$info->{'timeout'} = $conf->config('selfservice-timeout') || 3600;
+ $info->{'hide_usage'} = $conf->exists('selfservice_hide-usage');
+
return { %$info,
'custnum' => $custnum,
'access_pkgnum' => $session->{'pkgnum'},
);
$return{has_ship_address} = $cust_main->has_ship_address;
- $return{status} = $cust_main->status;
+ $return{status} = $cust_main->status_label; #$cust_main->status; #better to break anyone obscurely testing for strings in self-service than to have to upgrade every front-end to get the new status to display
$return{statuscolor} = $cust_main->statuscolor;
+ $return{status_label} = $cust_main->status_label;
# compatibility: some places in selfservice use this to determine
# if there's a ship address
1, ##nobalance
);
-warn $return{first} = $cust_main->first;
-warn $return{'last'} = $cust_main->get('last');
+ $return{first} = $cust_main->first;
+ $return{'last'} = $cust_main->get('last');
$return{name} = $cust_main->first. ' '. $cust_main->get('last');
$return{payby} = $cust_main->payby;
$payby = $1;
}
+ my $conf = new FS::Conf;
+
if ( $payby =~ /^(CARD|DCRD)$/ ) {
$new->paydate($p->{'year'}. '-'. $p->{'month'}. '-01');
$new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' );
+ if ( $conf->exists('selfservice-onfile_require_cvv') ){
+ return { 'error' => 'CVV2 is required' } unless $p->{'paycvv'};
+ }
+
} elsif ( $payby =~ /^(CHEK|DCHK)$/ ) {
my $payinfo;
'card_types' => card_types(),
+ 'withcvv' => $conf->exists('selfservice-require_cvv'), #or enable optional cvv?
+ 'require_cvv' => $conf->exists('selfservice-require_cvv'),
+ 'onfile_require_cvv' => $conf->exists('selfservice-onfile_require_cvv'),
+
'paytypes' => [ @FS::cust_main::paytypes ],
'paybys' => [ $conf->config('signup_server-payby') ],
#doubleclick protection
my $_date = time;
- $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32;
+ $return{payunique} = "webui-MyAccount-$_date-$$-". rand() * 2**32; #new
+ $return{paybatch} = $return{payunique}; #back compat
return { 'error' => '',
%return,
or return { 'error' => gettext('illegal_name'). " payname: ". $p->{'payname'} };
my $payname = $1;
+ $p->{'payunique'} =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/
+ or return { 'error' => gettext('illegal_text'). " payunique: ". $p->{'payunique'} };
+ my $payunique = $1;
+
$p->{'paybatch'} =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/
or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} };
my $paybatch = $1;
+ $payunique = $paybatch if ! length($payunique) && length($paybatch);
+
$p->{'payby'} ||= 'CARD';
$p->{'payby'} =~ /^([A-Z]{4})$/
or return { 'error' => "illegal_payby " . $p->{'payby'} };
$payinfo = $p->{'payinfo'};
+ my $onfile = 0;
+
#more intelligent matching will be needed here if you change
#card_masking_method and don't remove existing paymasks
- $payinfo = $cust_main->payinfo
- if $cust_main->paymask eq $payinfo;
+ if ( $cust_main->paymask eq $payinfo ) {
+ $payinfo = $cust_main->payinfo;
+ $onfile = 1;
+ }
$payinfo =~ s/\D//g;
$payinfo =~ /^(\d{13,16}|\d{8,9})$/
or return { 'error' => "CVV2 (CVC2/CID) is three digits." };
$paycvv = $1;
}
+ } elsif ( $conf->exists('selfservice-onfile_require_cvv') ) {
+ return { 'error' => 'CVV2 is required' };
+ } elsif ( !$onfile && $conf->exists('selfservice-require_cvv') ) {
+ return { 'error' => 'CVV2 is required' };
}
} else {
'month' => $p->{'month'},
'year' => $p->{'year'},
'payname' => $payname,
- 'paybatch' => $paybatch, #this doesn't actually do anything
+ 'payunique' => $payunique,
+ 'paybatch' => $paybatch,
'paycvv' => $paycvv,
'payname' => $payname,
'discount_term' => $discount_term,
if ( $cust_pay ) {
- my($gw, $auth, $order) = split(':', $cust_pay->paybatch);
-
return {
'error' => '',
'amount' => sprintf('%.2f', $cust_pay->paid),
'date' => $cust_pay->_date,
'date_pretty' => time2str('%Y-%m-%d', $cust_pay->_date),
'time_pretty' => time2str('%T', $cust_pay->_date),
- 'auth_num' => $auth,
- 'order_num' => $order,
+ 'auth_num' => $cust_pay->auth,
+ 'order_num' => $cust_pay->order_number,
'receipt_html' => $receipt_html,
};
or return { 'error' => "unknown custnum $custnum" };
my $conf = new FS::Conf;
+ my $immutable = $conf->exists('selfservice_immutable-package');
# the duplication below is necessary:
# 1. to maintain the current buggy behaviour wrt the cust_pkg and part_pkg
'custnum' => $custnum,
'cust_pkg' => [ map {
{ $_->hash,
+ immutable => $immutable,
part_pkg => [ map $_->hashref, $_->part_pkg ],
part_svc =>
[ map $_->hashref, $_->available_part_svc ],
my $primary_cust_svc = $_->primary_cust_svc;
+{ $_->hash,
$_->part_pkg->hash,
+ immutable => $immutable,
pkg_label => $_->pkg_locale,
status => $_->status,
statuscolor => $_->statuscolor,
my $tag = $part->description . ($part->shared ? 1 : 0);
my $row = $usage_pools{$tag}
||= [ $part->description, 0, 0, $part->shared ? 1 : 0 ];
- $row->[1] += $_->minutes; # minutes remaining
+ $row->[1] += sprintf('%.1f', $_->minutes); # minutes remaining
$row->[2] += $part->minutes; # minutes total
}
'inbound' => ( $_ eq 'inbound' ? 1 : 0 ),
'begin' => ($cust_pkg->last_bill || 0),
'nonzero' => 1,
+ 'disable_charged_party' => 1,
);
$hash{$_} = $sum_cdr->hashref;
}
# we have to return the results all at once...
my($svc_phone, $begin, $end, %opt) = @_;
map [ $_->downstream_csv(%opt, 'keeparray' => 1) ],
- $svc_phone->get_cdrs( 'begin'=>$begin, 'end'=>$end, %opt );
+ $svc_phone->get_cdrs(
+ 'begin'=>$begin,
+ 'end'=>$end,
+ 'disable_charged_party' => 1,
+ %opt
+ );
}
sub list_cdr_usage {
sub _usage_details {
my($callback, $p, %opt) = @_;
+ my $conf = FS::Conf->new;
my($context, $session, $custnum) = _custoragent_session_custnum($p);
return { 'error' => $session } if $context eq 'error';
my %callback_opt;
my $header = [];
if ( $svcdb eq 'svc_phone' ) {
- my $conf = FS::Conf->new;
my $format = '';
if ( $p->{inbound} ) {
$format = $cust_pkg->part_pkg->option('selfservice_inbound_format')
%callback_opt
);
+ if ( $conf->exists('selfservice-hide_cdr_price') ) {
+ # ugly kludge, I know
+ my ($delete_col) = grep { $header->[$_] eq 'Price' } (0..scalar(@$header));
+ if (defined $delete_col) {
+ delete($_->[$delete_col]) foreach ($header, @usage);
+ }
+ }
+
#kinda false laziness with FS::cust_main::bill, but perhaps
#we should really change this bit to DateTime and DateTime::Duration
#
my($context, $session, $custnum) = _custoragent_session_custnum($p);
return { 'error' => $session } if $context eq 'error';
+ my $conf = new FS::Conf;
+ my $immutable = $conf->exists('selfservice_immutable-package');
+ return { 'error' => "Package modification disabled" } if $immutable;
+
my $search = { 'custnum' => $custnum };
$search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
my $cust_main = qsearchs('cust_main', $search )
\@newpkg,
);
- my $conf = new FS::Conf;
if ( $conf->exists('signup_server-realtime') ) {
my $bill_error = _do_bop_realtime( $cust_main, $status, 'no_credit'=>1 );
my $error = '';
my $conf = new FS::Conf;
+
+ return { 'error' => 'Incorrect current password.' }
+ if ( exists($p->{'old_password'})
+ || $conf->exists('selfservice-password_change_oldpass')
+ )
+ && ! $svc_acct->check_password($p->{'old_password'});
+
$error = 'Password too short.'
if length($p->{'new_password'}) < ($conf->config('passwordmin') || 6);
$error = 'Password too long.'
my($context, $session, $custnum) = _custoragent_session_custnum($p);
return { 'error' => $session } if $context eq 'error';
-# warn "$me create_ticket: initializing ticket system\n" if $DEBUG;
-# FS::TicketSystem->init();
+ warn "$me create_ticket: initializing ticket system\n" if $DEBUG;
+ FS::TicketSystem->init();
my $conf = new FS::Conf;
my $queue = $p->{'queue'}