use HTML::Entities;
use Text::CSV_XS;
use Spreadsheet::WriteExcel;
+use OLE::Storage_Lite;
use FS::UI::Web::small_custview qw(small_custview); #less doh
use FS::UI::Web;
use FS::UI::bytecount qw( display_bytecount );
use FS::acct_rt_transaction;
use FS::msg_template;
-$DEBUG = 0;
+$DEBUG = 1;
$me = '[FS::ClientAPI::MyAccount]';
use vars qw( @cust_main_editable_fields @location_editable_fields );
font title_color title_align title_size menu_bgcolor menu_fontsize
)
),
+ 'menu_disable' => [ $conf->config('selfservice-menu_disable',$agentnum) ],
( map { $_ => $conf->exists("selfservice-$_", $agentnum ) }
qw( menu_skipblanks menu_skipheadings menu_nounderline no_logo )
),
$return{balance} = $cust_main->balance;
$return{next_bill_date} = $cust_main->next_bill_date;
$return{next_bill_date_pretty} =
- time2str('%m/%d/%Y', $return{next_bill_date} );
+ $return{next_bill_date} ? time2str('%m/%d/%Y', $return{next_bill_date} )
+ : '(none)';
}
my @tickets = $cust_main->tickets;
# unavoidable false laziness w/ httemplate/view/cust_main/tickets.html
- if ( FS::TicketSystem->selfservice_priority ) {
+ if ( $FS::TicketSystem::system && FS::TicketSystem->selfservice_priority ) {
my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1;
$return{tickets} = [
sort {
$return{balance} = $cust_main->balance;
$return{next_bill_date} = $cust_main->next_bill_date;
$return{next_bill_date_pretty} =
- time2str('%m/%d/%Y', $return{next_bill_date} );
+ $return{next_bill_date} ? time2str('%m/%d/%Y', $return{next_bill_date} )
+ : '(none)';
my @history = ();
#changing the hidden form values
my $conf = new FS::Conf;
my $fee_display = $conf->config('selfservice_process-display') || 'add';
- my $fee_pkgpart = $conf->config('selfservice_process-pkgpart');
+ my $fee_pkgpart = $conf->config('selfservice_process-pkgpart', $cust_main->agentnum);
my $fee_skip_first = $conf->exists('selfservice_process-skip_first');
if ( $fee_display eq 'add'
and $fee_pkgpart
#no error, so order the fee package if applicable...
my $conf = new FS::Conf;
- my $fee_pkgpart = $conf->config('selfservice_process-pkgpart');
+ my $fee_pkgpart = $conf->config('selfservice_process-pkgpart', $cust_main->agentnum);
my $fee_skip_first = $conf->exists('selfservice_process-skip_first');
if ( $fee_pkgpart and ! $fee_skip_first || scalar($cust_main->cust_pay) ) {
pkg_label => $_->pkg_label,
status => $_->status,
part_svc =>
- [ map $_->hashref, $_->available_part_svc ],
+ [ map { $_->hashref }
+ grep { $_->selfservice_access ne 'hidden' }
+ $_->available_part_svc
+ ],
cust_svc =>
[ map { my $ref = { $_->hash,
label => [ $_->label ],
$ref->{svchash}->{svcpart} = $_->part_svc->svcpart
if $_->part_svc->svcdb eq 'svc_phone'; # hack
$ref;
- } $_->cust_svc
+ }
+ grep { $_->part_svc->selfservice_access ne 'hidden' }
+ $_->cust_svc
],
primary_cust_svc =>
$primary_cust_svc
}
my @cust_svc = ();
+ my @cust_pkg_usage = ();
#foreach my $cust_pkg ( $cust_main->ncancelled_pkgs ) {
foreach my $cust_pkg ( $p->{'ncancelled'}
? $cust_main->ncancelled_pkgs
: $cust_main->unsuspended_pkgs ) {
next if $pkgnum && $cust_pkg->pkgnum != $pkgnum;
push @cust_svc, @{[ $cust_pkg->cust_svc ]}; #@{[ ]} to force array context
+ push @cust_pkg_usage, $cust_pkg->cust_pkg_usage;
}
@cust_svc = grep { $_->part_svc->selfservice_access ne 'hidden' } @cust_svc;
+ my %usage_pools;
+ foreach (@cust_pkg_usage) {
+ my $part = $_->part_pkg_usage;
+ 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->[2] += $part->minutes; # minutes total
+ }
if ( $p->{'svcdb'} ) {
my $svcdb = ref($p->{'svcdb'}) eq 'HASH'
} else {
$hash{'name'} = $cust_main->name;
}
+ } elsif ( $svcdb eq 'svc_phone' ) {
+ # could potentially show lots of things...
+ $hash{'outbound'} = 1;
+ $hash{'inbound'} = 0;
+ if ( $part_pkg->plan eq 'voip_inbound' ) {
+ $hash{'outbound'} = 0;
+ $hash{'inbound'} = 1;
+ } elsif ( $part_pkg->option('selfservice_inbound_format')
+ or $conf->config('selfservice-default_inbound_cdr_format')
+ ) {
+ $hash{'inbound'} = 1;
+ }
+ foreach (qw(inbound outbound)) {
+ # hmm...we can't filter by status here, because there might
+ # not be cdr_terminations at all. have to go by date.
+ # find all since the last bill date.
+ # XXX cdr types? we are going to need them.
+ if ( $hash{$_} ) {
+ my $sum_cdr = $svc_x->sum_cdrs(
+ 'inbound' => ( $_ eq 'inbound' ? 1 : 0 ),
+ 'begin' => ($cust_pkg->last_bill || 0),
+ 'nonzero' => 1,
+ );
+ $hash{$_} = $sum_cdr->hashref;
+ }
+ }
}
+
# elsif ( $svcdb eq 'svc_phone' || $svcdb eq 'svc_port' ) {
# %hash = (
# %hash,
}
@cust_svc
],
+ 'usage_pools' => [
+ map { $usage_pools{$_} }
+ sort { $a cmp $b }
+ keys %usage_pools
+ ],
};
}
}
-sub set_svc_status_hash {
- my $p = shift;
+sub set_svc_status_hash { _svc_method_X(shift, 'export_setstatus') }
+sub set_svc_status_listadd { _svc_method_X(shift, 'export_setstatus_listadd') }
+sub set_svc_status_listdel { _svc_method_X(shift, 'export_setstatus_listdel') }
+sub set_svc_status_vacationadd { _svc_method_X(shift, 'export_setstatus_vacationadd') }
+sub set_svc_status_vacationdel { _svc_method_X(shift, 'export_setstatus_vacationdel') }
+
+sub _svc_method_X {
+ my( $p, $method ) = @_;
my($context, $session, $custnum) = _custoragent_session_custnum($p);
return { 'error' => $session } if $context eq 'error';
my $svc_x = _customer_svc_x( $custnum, $p->{'svcnum'}, 'svc_acct')
or return { 'error' => "Service not found" };
- warn "set_svc_status_hash ". join(' / ', map "$_=>".$p->{$_}, keys %$p )
+ warn "$method ". join(' / ', map "$_=>".$p->{$_}, keys %$p )
if $DEBUG;
- my $error = $svc_x->export_setstatus($p); #$p? returns error?
+ my $error = $svc_x->$method($p); #$p? returns error?
return { 'error' => $error } if $error;
return {}; #? { 'error' => '' }
}
-
sub acct_forward_info {
my $p = shift;
# 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, );
+ $svc_phone->get_cdrs( 'begin'=>$begin, 'end'=>$end, %opt );
}
sub list_cdr_usage {
my %callback_opt;
my $header = [];
if ( $svcdb eq 'svc_phone' ) {
- my $format = $cust_pkg->part_pkg->option('output_format') || '';
- $format = '' if $format =~ /^sum_/;
- # sensible default if there is no format or it's a summary format
- if ( $cust_pkg->part_pkg->plan eq 'voip_inbound' ) {
- $format ||= 'source_default';
+ my $conf = FS::Conf->new;
+ my $format = '';
+ if ( $p->{inbound} ) {
+ $format = $cust_pkg->part_pkg->option('selfservice_inbound_format')
+ || $conf->config('selfservice-default_inbound_cdr_format')
+ || 'source_default';
$callback_opt{inbound} = 1;
+ } else {
+ $format = $cust_pkg->part_pkg->option('selfservice_format')
+ || $conf->config('selfservice-default_cdr_format')
+ || 'default';
}
- else {
- $format ||= 'default';
- }
-
+
$callback_opt{format} = $format;
+ $callback_opt{use_clid} = 1;
$header = [ split(',', FS::cdr::invoice_header($format) ) ];
}
$p->{ending} = $end;
}
+ die "illegal beginning" if $p->{beginning} !~ /^\d*$/;
+ die "illegal ending" if $p->{ending} !~ /^\d*$/;
+
my (@usage) = &$callback($svc_x, $p->{beginning}, $p->{ending},
%callback_opt
);
'svcnum' => $p->{svcnum},
'beginning' => $p->{beginning},
'ending' => $p->{ending},
+ 'inbound' => $p->{inbound},
'previous' => ($previous > $start) ? $previous : $start,
'next' => ($next < $end) ? $next : $end,
'header' => $header,