OPTIONS may contain:
- buffer: an arrayref to store details into. This may avoid the need for a
-large copy operation at the end of processing. However, since summary formats
-will produce nothing until the end of processing, C<finish> must be called
-after all CDRs have been appended.
+large copy operation at the end of processing. However, since summary
+formats will produce nothing until the end of processing, C<finish> must be
+called after all CDRs have been appended.
- inbound: a flag telling the formatter to format CDRs for display to the
receiving party, rather than the originator. In this case, the
- locale: a locale string to use for static text and date formats. This is
optional.
+- rounding: the number of decimal places to show in the amount column. This
+is optional, and defaults to whatever's in the schema (which is 4).
+
=cut
sub new {
my $self = { conf => FS::Conf->new({ locale => $locale }),
csv => Text::CSV_XS->new({ binary => 1 }),
inbound => ($opt{'inbound'} ? 1 : 0),
+ rounding => $opt{'rounding'},
buffer => ($opt{'buffer'} || []),
_lh => FS::L10N->get_handle($locale),
_dh => eval { Date::Language->new($language_name) } ||
accountcode => accountcode
startdate => startdate
+If the formatter is in inbound mode, it will look up a C<cdr_termination>
+record and use rated_price and rated_seconds from that, and acctid will be
+set to null to avoid linking the CDR to the detail record for the inbound
+leg of the call.
+
'phonenum' is set to the internal C<phonenum> value set on the formatter
object.
my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
my $price = $object->rated_price if $object;
$price = 0 if $cdr->freesidestatus eq 'no-charge';
+ $price = sprintf('%.*f', $self->{'rounding'}, $price)
+ if $self->{'rounding'} and length($price);
FS::cust_bill_pkg_detail->new( {
- 'acctid' => $cdr->acctid,
+ 'acctid' => ($self->{inbound} ? '' : $cdr->acctid),
'amount' => $price,
'classnum' => $cdr->rated_classnum,
- 'duration' => $cdr->rated_seconds,
+ 'duration' => $object->rated_seconds,
'regionname' => $cdr->rated_regionname,
'accountcode' => $cdr->accountcode,
'startdate' => $cdr->startdate,
my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
my $sec = $object->rated_seconds if $object;
$sec ||= 0;
- # XXX termination objects don't have rated_granularity so this may
- # result in inbound CDRs being displayed as min/sec when they shouldn't.
- # Should probably fix this.
- if ( $cdr->rated_granularity eq '0' ) {
+ # termination objects now have rated_granularity.
+ if ( $object->rated_granularity eq '0' ) {
'1 call';
}
- elsif ( $cdr->rated_granularity eq '60' ) {
+ elsif ( $object->rated_granularity eq '60' ) {
sprintf('%dm', ($sec + 59)/60);
}
else {
my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
my $price = $object->rated_price if $object;
$price = '0.00' if $object->freesidestatus eq 'no-charge';
- length($price) ? $self->money_char . $price : '';
+ $price = sprintf('%.*f', $self->{'rounding'}, $price)
+ if $self->{'rounding'};
+ if (length($price)) {
+ $price = sprintf('%.*f', $self->{'rounding'}, $price)
+ if $self->{'rounding'};
+ return $self->money_char . $price;
+ } else {
+ return '';
+ }
}
1;