From 0d16979c948a691c95ef92f4ac7a2921a9e8c998 Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 3 Jan 2012 21:13:33 +0000 Subject: detail format refactor, #15535 --- FS/FS/detail_format/accountcode_default.pm | 25 +++++++++ FS/FS/detail_format/basic.pm | 22 ++++++++ FS/FS/detail_format/default.pm | 24 ++++++++ FS/FS/detail_format/description_default.pm | 25 +++++++++ FS/FS/detail_format/simple.pm | 24 ++++++++ FS/FS/detail_format/simple2.pm | 25 +++++++++ FS/FS/detail_format/source_default.pm | 25 +++++++++ FS/FS/detail_format/sum_count.pm | 77 +++++++++++++++++++++++++ FS/FS/detail_format/sum_duration.pm | 79 ++++++++++++++++++++++++++ FS/FS/detail_format/sum_duration_prefix.pm | 90 ++++++++++++++++++++++++++++++ 10 files changed, 416 insertions(+) create mode 100644 FS/FS/detail_format/accountcode_default.pm create mode 100644 FS/FS/detail_format/basic.pm create mode 100644 FS/FS/detail_format/default.pm create mode 100644 FS/FS/detail_format/description_default.pm create mode 100644 FS/FS/detail_format/simple.pm create mode 100644 FS/FS/detail_format/simple2.pm create mode 100644 FS/FS/detail_format/source_default.pm create mode 100644 FS/FS/detail_format/sum_count.pm create mode 100644 FS/FS/detail_format/sum_duration.pm create mode 100644 FS/FS/detail_format/sum_duration_prefix.pm (limited to 'FS/FS/detail_format') 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; -- cgit v1.1