+sub list_svcs {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $search = { 'custnum' => $custnum };
+ $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
+ my $cust_main = qsearchs('cust_main', $search )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ my @cust_svc = ();
+ #foreach my $cust_pkg ( $cust_main->ncancelled_pkgs ) {
+ foreach my $cust_pkg ( $p->{'ncancelled'}
+ ? $cust_main->ncancelled_pkgs
+ : $cust_main->unsuspended_pkgs ) {
+ push @cust_svc, @{[ $cust_pkg->cust_svc ]}; #@{[ ]} to force array context
+ }
+ @cust_svc = grep { $_->part_svc->svcdb eq $p->{'svcdb'} } @cust_svc
+ if $p->{'svcdb'};
+
+ #@svc_x = sort { $a->domain cmp $b->domain || $a->username cmp $b->username }
+ # @svc_x;
+
+ {
+ #no#'svcnum' => $session->{'svcnum'},
+ 'custnum' => $custnum,
+ 'svcs' => [ map {
+ my $svc_x = $_->svc_x;
+ my($label, $value) = $_->label;
+ my $part_pkg = $svc_x->cust_svc->cust_pkg->part_pkg;
+
+ { 'svcnum' => $_->svcnum,
+ 'label' => $label,
+ 'value' => $value,
+ 'username' => $svc_x->username,
+ 'email' => $svc_x->email,
+ 'seconds' => $svc_x->seconds,
+ 'upbytes' => FS::UI::bytecount::display_bytecount($svc_x->upbytes),
+ 'downbytes' => FS::UI::bytecount::display_bytecount($svc_x->downbytes),
+ 'totalbytes'=> FS::UI::bytecount::display_bytecount($svc_x->totalbytes),
+ 'recharge_amount' => $part_pkg->option('recharge_amount', 1),
+ 'recharge_seconds' => $part_pkg->option('recharge_seconds', 1),
+ 'recharge_upbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_upbytes', 1)),
+ 'recharge_downbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_downbytes', 1)),
+ 'recharge_totalbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_totalbytes', 1)),
+ # more...
+ };
+ }
+ @cust_svc
+ ],
+ };
+
+}
+
+sub _list_svc_usage {
+ my($svc_acct, $begin, $end) = @_;
+ my @usage = ();
+ foreach my $part_export (
+ map { qsearch ( 'part_export', { 'exporttype' => $_ } ) }
+ qw (sqlradius sqlradius_withdomain')
+ ) {
+
+ push @usage, @ { $part_export->usage_sessions($begin, $end, $svc_acct) };
+ }
+ (@usage);
+}
+
+sub list_svc_usage {
+ _usage_details(\&_list_svc_usage, @_);
+}
+
+sub _list_support_usage {
+ my($svc_acct, $begin, $end) = @_;
+ my @usage = ();
+ foreach ( grep { $begin <= $_->_date && $_->_date <= $end }
+ qsearch('acct_rt_transaction', { 'svcnum' => $svc_acct->svcnum })
+ ) {
+ push @usage, { 'seconds' => $_->seconds,
+ 'support' => $_->support,
+ '_date' => $_->_date,
+ 'id' => $_->transaction_id,
+ 'creator' => $_->creator,
+ 'subject' => $_->subject,
+ 'status' => $_->status,
+ 'ticketid' => $_->ticketid,
+ };
+ }
+ (@usage);
+}
+
+sub list_support_usage {
+ _usage_details(\&_list_support_usage, @_);
+}
+
+sub _usage_details {
+ my ($callback, $p) = (shift,shift);
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $search = { 'svcnum' => $p->{'svcnum'} };
+ $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
+ my $svc_acct = qsearchs ( 'svc_acct', $search );
+ return { 'error' => 'No service selected in list_svc_usage' }
+ unless $svc_acct;
+
+ my $freq = $svc_acct->cust_svc->cust_pkg->part_pkg->freq;
+ my $start = $svc_acct->cust_svc->cust_pkg->setup;
+ #my $end = $svc_acct->cust_svc->cust_pkg->bill; # or time?
+ my $end = time;
+
+ unless($p->{beginning}){
+ $p->{beginning} = $svc_acct->cust_svc->cust_pkg->last_bill;
+ $p->{ending} = $end;
+ }
+
+ my (@usage) = &$callback($svc_acct,$p->{beginning},$p->{ending});
+
+ #kinda false laziness with FS::cust_main::bill, but perhaps
+ #we should really change this bit to DateTime and DateTime::Duration
+ #
+ #change this bit to use Date::Manip? CAREFUL with timezones (see
+ # mailing list archive)
+ my ($nsec,$nmin,$nhour,$nmday,$nmon,$nyear) =
+ (localtime($p->{ending}) )[0,1,2,3,4,5];
+ my ($psec,$pmin,$phour,$pmday,$pmon,$pyear) =
+ (localtime($p->{beginning}) )[0,1,2,3,4,5];
+
+ if ( $freq =~ /^\d+$/ ) {
+ $nmon += $freq;
+ until ( $nmon < 12 ) { $nmon -= 12; $nyear++; }
+ $pmon -= $freq;
+ until ( $pmon >= 0 ) { $pmon += 12; $pyear--; }
+ } elsif ( $freq =~ /^(\d+)w$/ ) {
+ my $weeks = $1;
+ $nmday += $weeks * 7;
+ $pmday -= $weeks * 7;
+ } elsif ( $freq =~ /^(\d+)d$/ ) {
+ my $days = $1;
+ $nmday += $days;
+ $pmday -= $days;
+ } elsif ( $freq =~ /^(\d+)h$/ ) {
+ my $hours = $1;
+ $nhour += $hours;
+ $phour -= $hours;
+ } else {
+ return { 'error' => "unparsable frequency: ". $freq };
+ }
+
+ my $previous = timelocal_nocheck($psec,$pmin,$phour,$pmday,$pmon,$pyear);
+ my $next = timelocal_nocheck($nsec,$nmin,$nhour,$nmday,$nmon,$nyear);
+
+ {
+ 'error' => '',
+ 'svcnum' => $p->{svcnum},
+ 'beginning' => $p->{beginning},
+ 'ending' => $p->{ending},
+ 'previous' => ($previous > $start) ? $previous : $start,
+ 'next' => ($next < $end) ? $next : $end,
+ 'usage' => \@usage,
+ };
+}
+