summaryrefslogtreecommitdiff
path: root/FS/FS/detail_format
diff options
context:
space:
mode:
authormark <mark>2012-01-03 21:13:33 +0000
committermark <mark>2012-01-03 21:13:33 +0000
commit0d16979c948a691c95ef92f4ac7a2921a9e8c998 (patch)
treefca3c5c23008380183c4ffa566525d95fb2bc820 /FS/FS/detail_format
parentc9c9f28394024d03f78c61b37811e4816aa73c9a (diff)
detail format refactor, #15535
Diffstat (limited to 'FS/FS/detail_format')
-rw-r--r--FS/FS/detail_format/accountcode_default.pm25
-rw-r--r--FS/FS/detail_format/basic.pm22
-rw-r--r--FS/FS/detail_format/default.pm24
-rw-r--r--FS/FS/detail_format/description_default.pm25
-rw-r--r--FS/FS/detail_format/simple.pm24
-rw-r--r--FS/FS/detail_format/simple2.pm25
-rw-r--r--FS/FS/detail_format/source_default.pm25
-rw-r--r--FS/FS/detail_format/sum_count.pm77
-rw-r--r--FS/FS/detail_format/sum_duration.pm79
-rw-r--r--FS/FS/detail_format/sum_duration_prefix.pm90
10 files changed, 416 insertions, 0 deletions
diff --git a/FS/FS/detail_format/accountcode_default.pm b/FS/FS/detail_format/accountcode_default.pm
new file mode 100644
index 0000000..031cc4b
--- /dev/null
+++ b/FS/FS/detail_format/accountcode_default.pm
@@ -0,0 +1,25 @@
+package FS::detail_format::accountcode_default;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Default with accountcode' }
+
+sub header_detail { 'Date,Time,Account,Number,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ $cdr->accountcode,
+ ($cdr->rated_pretty_dst || $cdr->dst),
+ $cdr->rated_regionname,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/basic.pm b/FS/FS/detail_format/basic.pm
new file mode 100644
index 0000000..21b5da4
--- /dev/null
+++ b/FS/FS/detail_format/basic.pm
@@ -0,0 +1,22 @@
+package FS::detail_format::basic;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Basic' }
+
+sub header_detail { 'Date/Time,Called Number,Min/Sec,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ time2str('%d %b - %I:%M %p', $cdr->startdate),
+ $cdr->dst,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/default.pm b/FS/FS/detail_format/default.pm
new file mode 100644
index 0000000..33abb09
--- /dev/null
+++ b/FS/FS/detail_format/default.pm
@@ -0,0 +1,24 @@
+package FS::detail_format::default;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Default' }
+
+sub header_detail { 'Date,Time,Number,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ ($cdr->rated_pretty_dst || $cdr->dst),
+ $cdr->rated_regionname,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/description_default.pm b/FS/FS/detail_format/description_default.pm
new file mode 100644
index 0000000..b00983d
--- /dev/null
+++ b/FS/FS/detail_format/description_default.pm
@@ -0,0 +1,25 @@
+package FS::detail_format::description_default;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Default with description field as destination' }
+
+sub header_detail { 'Caller,Date,Time,Number,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ $cdr->src,
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ ($cdr->rated_pretty_dst || $cdr->dst),
+ $cdr->description,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/simple.pm b/FS/FS/detail_format/simple.pm
new file mode 100644
index 0000000..cb6b672
--- /dev/null
+++ b/FS/FS/detail_format/simple.pm
@@ -0,0 +1,24 @@
+package FS::detail_format::simple;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Simple' }
+
+sub header_detail { 'Date,Time,Name,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ $cdr->userfield,
+ $cdr->dst,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/simple2.pm b/FS/FS/detail_format/simple2.pm
new file mode 100644
index 0000000..5bba18d
--- /dev/null
+++ b/FS/FS/detail_format/simple2.pm
@@ -0,0 +1,25 @@
+package FS::detail_format::simple2;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Simple with source' }
+
+sub header_detail { 'Date,Time,Name,Called From,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ $cdr->userfield,
+ $cdr->src,
+ $cdr->dst,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/source_default.pm b/FS/FS/detail_format/source_default.pm
new file mode 100644
index 0000000..26c1146
--- /dev/null
+++ b/FS/FS/detail_format/source_default.pm
@@ -0,0 +1,25 @@
+package FS::detail_format::source_default;
+
+use strict;
+use parent qw(FS::detail_format);
+use Date::Format qw(time2str);
+
+sub name { 'Default with source' }
+
+sub header_detail { 'Caller,Date,Time,Number,Destination,Duration,Price' }
+
+sub columns {
+ my $self = shift;
+ my $cdr = shift;
+ (
+ $cdr->src,
+ time2str($self->date_format, $cdr->startdate),
+ time2str('%r', $cdr->startdate),
+ ($cdr->rated_pretty_dst || $cdr->dst),
+ $cdr->rated_regionname,
+ $self->duration($cdr),
+ $self->price($cdr),
+ )
+}
+
+1;
diff --git a/FS/FS/detail_format/sum_count.pm b/FS/FS/detail_format/sum_count.pm
new file mode 100644
index 0000000..8c395e8
--- /dev/null
+++ b/FS/FS/detail_format/sum_count.pm
@@ -0,0 +1,77 @@
+package FS::detail_format::sum_count;
+
+use strict;
+use vars qw( $DEBUG );
+use parent qw(FS::detail_format);
+use FS::Record qw(qsearchs);
+use FS::cust_svc;
+use FS::svc_Common; # for label
+
+$DEBUG = 0;
+
+sub name { 'Number of calls, one line per service' };
+
+sub header_detail {
+ my $self = shift;
+ if ( $self->{inbound} ) {
+ 'Destination,Messages,Price'
+ }
+ else {
+ 'Source,Messages,Price'
+ }
+}
+
+sub append {
+ my $self = shift;
+ my $svcnums = ($self->{svcnums} ||= {});
+ foreach my $cdr (@_) {
+ my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
+ my $svcnum = $object->svcnum; # yes, $object->svcnum.
+
+ my $subtotal = ($svcnums->{$svcnum} ||=
+ { count => 0, duration => 0, amount => 0 });
+ $subtotal->{count}++;
+ $subtotal->{amount} += $object->rated_price;
+ }
+}
+
+sub finish {
+ my $self = shift;
+ my $svcnums = $self->{svcnums};
+ my $buffer = $self->{buffer};
+ foreach my $svcnum (keys %$svcnums) {
+
+ my $cust_svc = qsearchs('cust_svc', { svcnum => $svcnum })
+ or die "svcnum #$svcnum not found";
+ my $phonenum = $cust_svc->svc_x->label;
+ warn "processing $phonenum\n" if $DEBUG;
+
+ my $subtotal = $svcnums->{$svcnum};
+
+ $self->csv->combine(
+ $phonenum,
+ $subtotal->{count},
+ $self->money_char . sprintf('%.02f',$subtotal->{amount}),
+ );
+
+ warn "adding detail: ".$self->csv->string."\n" if $DEBUG;
+
+ push @$buffer, FS::cust_bill_pkg_detail->new({
+ amount => $subtotal->{amount},
+ format => 'C',
+ classnum => '', #ignored in this format
+ duration => '',
+ phonenum => $phonenum,
+ accountcode => '', #ignored in this format
+ startdate => '', #could use the earliest startdate in the bunch?
+ regionname => '', #no, we're using prefix instead
+ detail => $self->csv->string,
+ });
+ } #foreach $svcnum
+
+ # supposedly the compiler is smart enough to do this in place
+ @$buffer = sort { $a->{Hash}->{phonenum} cmp $b->{Hash}->{phonenum} }
+ @$buffer;
+}
+
+1;
diff --git a/FS/FS/detail_format/sum_duration.pm b/FS/FS/detail_format/sum_duration.pm
new file mode 100644
index 0000000..0b4cedc
--- /dev/null
+++ b/FS/FS/detail_format/sum_duration.pm
@@ -0,0 +1,79 @@
+package FS::detail_format::sum_duration;
+
+use strict;
+use vars qw( $DEBUG );
+use parent qw(FS::detail_format);
+use FS::Record qw(qsearchs);
+use FS::cust_svc;
+use FS::svc_Common; # for label
+
+$DEBUG = 0;
+
+sub name { 'Summary, one line per service' };
+
+sub header_detail {
+ my $self = shift;
+ if ( $self->{inbound} ) {
+ 'Destination,Calls,Duration,Price'
+ }
+ else {
+ 'Source,Calls,Duration,Price'
+ }
+}
+
+sub append {
+ my $self = shift;
+ my $svcnums = ($self->{svcnums} ||= {});
+ foreach my $cdr (@_) {
+ my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
+ my $svcnum = $object->svcnum; # yes, $object->svcnum.
+
+ my $subtotal = ($svcnums->{$svcnum} ||=
+ { count => 0, duration => 0, amount => 0 });
+ $subtotal->{count}++;
+ $subtotal->{duration} += $object->rated_seconds;
+ $subtotal->{amount} += $object->rated_price;
+ }
+}
+
+sub finish {
+ my $self = shift;
+ my $svcnums = $self->{svcnums};
+ my $buffer = $self->{buffer};
+ foreach my $svcnum (keys %$svcnums) {
+
+ my $cust_svc = qsearchs('cust_svc', { svcnum => $svcnum })
+ or die "svcnum #$svcnum not found";
+ my $phonenum = $cust_svc->svc_x->label;
+ warn "processing $phonenum\n" if $DEBUG;
+
+ my $subtotal = $svcnums->{$svcnum};
+
+ $self->csv->combine(
+ $phonenum,
+ $subtotal->{count},
+ int($subtotal->{duration}/60) . ' min',
+ $self->money_char . sprintf('%.02f',$subtotal->{amount}),
+ );
+
+ warn "adding detail: ".$self->csv->string."\n" if $DEBUG;
+
+ push @$buffer, FS::cust_bill_pkg_detail->new({
+ amount => $subtotal->{amount},
+ format => 'C',
+ classnum => '', #ignored in this format
+ duration => $subtotal->{duration},
+ phonenum => $phonenum,
+ accountcode => '', #ignored in this format
+ startdate => '', #could use the earliest startdate in the bunch?
+ regionname => '', #no, we're using prefix instead
+ detail => $self->csv->string,
+ });
+ } #foreach $svcnum
+
+ # supposedly the compiler is smart enough to do this in place
+ @$buffer = sort { $a->{Hash}->{phonenum} cmp $b->{Hash}->{phonenum} }
+ @$buffer;
+}
+
+1;
diff --git a/FS/FS/detail_format/sum_duration_prefix.pm b/FS/FS/detail_format/sum_duration_prefix.pm
new file mode 100644
index 0000000..275aa57
--- /dev/null
+++ b/FS/FS/detail_format/sum_duration_prefix.pm
@@ -0,0 +1,90 @@
+package FS::detail_format::sum_duration_prefix;
+
+use strict;
+use vars qw( $DEBUG );
+use parent qw(FS::detail_format);
+use List::Util qw(sum);
+
+$DEBUG = 0;
+
+my $me = '[sum_duration_prefix]';
+
+sub name { 'Summary, one line per destination prefix' };
+# and also..."rate group"? what do you call the interstate/intrastate rate
+# distinction?
+
+sub header_detail {
+ 'Destination NPA-NXX,Interstate Calls,Duration,Intrastate Calls,Duration,Price';
+}
+
+my $prefix_length = 6;
+# possibly should use rate_prefix for this, but interstate/intrastate uses
+# them in a strange way and we are following along
+
+sub append {
+ my $self = shift;
+ my $prefixes = ($self->{prefixes} ||= {});
+ foreach my $cdr (@_) {
+ my $phonenum = $self->{inbound} ? $cdr->src : $cdr->dst;
+ $phonenum =~ /^(\d{$prefix_length})/;
+ my $prefix = $1 || 'other';
+ warn "$me appending ".$cdr->dst." to $prefix\n" if $DEBUG;
+
+ # XXX hardcoded ratenames, not the worst of evils
+ $prefixes->{$prefix} ||= {
+ Interstate => { count => 0, duration => 0, amount => 0 },
+ Intrastate => { count => 0, duration => 0, amount => 0 },
+ };
+ my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
+ # XXX using $cdr's rated_ratename instead of $object because
+ # cdr_termination doesn't have one...
+ # but interstate-ness should be symmetric, yes? if A places an
+ # interstate call to B, then B receives an interstate call from A.
+ my $subtotal = $prefixes->{$prefix}{$cdr->rated_ratename}
+ or die "unknown rated_ratename '" .$cdr->rated_ratename.
+ "' in CDR #".$cdr->acctid."\n";
+ $subtotal->{count}++;
+ $subtotal->{duration} += $object->rated_seconds;
+ $subtotal->{amount} += $object->rated_price;
+ }
+}
+
+sub finish {
+ my $self = shift;
+ my $prefixes = $self->{prefixes};
+ foreach my $prefix (sort { $a cmp $b } keys %$prefixes) {
+
+ warn "processing $prefix\n" if $DEBUG;
+
+ my $ratenames = $prefixes->{$prefix};
+ my @subtotals = ($ratenames->{'Interstate'}, $ratenames->{'Intrastate'});
+ my $total_amount = sum( map { $_->{'amount'} } @subtotals );
+ my $total_duration = sum( map { $_->{'duration'} } @subtotals );
+ $prefix =~ s/(...)(...)/$1 - $2/;
+
+ $self->csv->combine(
+ $prefix,
+ map({
+ ($_->{count} || ''),
+ ($_->{duration} ? int($_->{duration}/60) . ' min' : '')
+ } @subtotals ),
+ $self->money_char . sprintf('%.02f',$total_amount),
+ );
+
+ warn "adding detail: ".$self->csv->string."\n" if $DEBUG;
+
+ push @{ $self->{buffer} }, FS::cust_bill_pkg_detail->new({
+ amount => $total_amount,
+ format => 'C',
+ classnum => '', #ignored in this format
+ duration => $total_duration,
+ phonenum => '', # not divided up per service
+ accountcode => '', #ignored in this format
+ startdate => '', #could use the earliest startdate in the bunch?
+ regionname => '', #no, we're using prefix instead
+ detail => $self->csv->string,
+ });
+ } #foreach $prefix
+}
+
+1;