delete fees, RT#81713
[freeside.git] / FS / FS / detail_format / sum_duration_prefix.pm
1 package FS::detail_format::sum_duration_prefix;
2
3 use strict;
4 use vars qw( $DEBUG );
5 use base qw(FS::detail_format);
6 use List::Util qw(sum);
7
8 $DEBUG = 0;
9
10 my $me = '[sum_duration_prefix]';
11
12 sub name { 'Summary, one line per destination prefix' };
13 # and also..."rate group"?  what do you call the interstate/intrastate rate 
14 # distinction?
15
16 sub header_detail {
17   'Destination NPA-NXX,Interstate Calls,Duration,Intrastate Calls,Duration,Price';
18 }
19
20 my $prefix_length = 6;
21 # possibly should use rate_prefix for this, but interstate/intrastate uses 
22 # them in a strange way and we are following along
23
24 sub append {
25   my $self = shift;
26   my $prefixes = ($self->{prefixes} ||= {});
27   my $acctids = ($self->{acctids} ||= []);
28   foreach my $cdr (@_) {
29     my (undef, $phonenum) = $cdr->parse_number(
30       column => ( $self->{inbound} ? 'src' : 'dst' ),
31     );
32
33     $phonenum =~ /^(\d{$prefix_length})/;
34     my $prefix = $1 || 'other';
35     warn "$me appending ".$cdr->dst." to $prefix\n" if $DEBUG;
36
37     # XXX hardcoded ratenames, not the worst of evils
38     $prefixes->{$prefix} ||= { 
39       Interstate => { count => 0, duration => 0, amount => 0 }, 
40       Intrastate => { count => 0, duration => 0, amount => 0 }, 
41     };
42     my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
43     # XXX using $cdr's rated_ratename instead of $object because 
44     # cdr_termination doesn't have one...
45     # but interstate-ness should be symmetric, yes?  if A places an
46     # interstate call to B, then B receives an interstate call from A.
47     my $subtotal = $prefixes->{$prefix}{$cdr->rated_ratename}
48       or next; 
49       # silently skip calls that are neither interstate nor intrastate
50     #or die "unknown rated_ratename '" .$cdr->rated_ratename.
51     #         "' in CDR #".$cdr->acctid."\n";
52     $subtotal->{count}++;
53     $subtotal->{duration} += $object->rated_seconds;
54     $subtotal->{amount} += $object->rated_price
55       if $object->freesidestatus ne 'no-charge';
56
57     push @$acctids, $cdr->acctid;
58   }
59 }
60
61 sub finish {
62   my $self = shift;
63   my $prefixes = $self->{prefixes};
64   foreach my $prefix (sort { $a cmp $b } keys %$prefixes) {
65
66     warn "processing $prefix\n" if $DEBUG;
67
68     my $ratenames = $prefixes->{$prefix};
69     my @subtotals = ($ratenames->{'Interstate'}, $ratenames->{'Intrastate'});
70     my $total_amount   = sum( map { $_->{'amount'} } @subtotals );
71     my $total_duration = sum( map { $_->{'duration'} } @subtotals );
72     $prefix =~ s/(...)(...)/$1 - $2/;
73
74     next if $total_amount < 0.01;
75
76     $self->csv->combine(
77       $prefix,
78       map({ 
79           $_->{count},
80           sprintf('%.01f min', $_->{duration}/60),
81         } @subtotals ),
82       $self->money_char . sprintf('%.02f',$total_amount),
83     );
84
85     warn "adding detail: ".$self->csv->string."\n" if $DEBUG;
86
87     push @{ $self->{buffer} }, FS::cust_bill_pkg_detail->new({
88         amount      => $total_amount,
89         format      => 'C',
90         classnum    => '', #ignored in this format
91         duration    => $total_duration,
92         phonenum    => '', # not divided up per service
93         accountcode => '', #ignored in this format
94         startdate   => '', #could use the earliest startdate in the bunch?
95         regionname  => '', #no, we're using prefix instead
96         detail      => $self->csv->string,
97         acctid      => $self->{acctids},
98     });
99   } #foreach $prefix
100 }
101
102 1;