use FS::Conf;
use FS::cdr;
use FS::cust_bill_pkg_detail;
-use Date::Format qw(time2str);
+use FS::L10N;
+use Date::Language;
use Text::CSV_XS;
my $me = '[FS::detail_format]';
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.
+- 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.
-- inbound: a flag telling the formatter to format CDRs for display to
- the receiving party, rather than the originator. In this case, the
- L<FS::cdr_termination> object will be fetched and its values used for
- rated_price, rated_seconds, rated_minutes, and svcnum. This can be
- changed with the C<inbound> method.
+- inbound: a flag telling the formatter to format CDRs for display to the
+receiving party, rather than the originator. In this case, the
+L<FS::cdr_termination> object will be fetched and its values used for
+rated_price, rated_seconds, rated_minutes, and svcnum. This can be changed
+with the C<inbound> method.
+
+- locale: a locale string to use for static text and date formats. This is
+optional.
=cut
die "$me error loading $class: $@" if $@;
my %opt = @_;
- my $self = { conf => FS::Conf->new,
- csv => Text::CSV_XS->new,
+ my $locale = $opt{'locale'} || '';
+ my $conf = FS::Conf->new({ locale => $locale });
+ $locale ||= $conf->config('locale') || 'en_US';
+
+ my %locale_info = FS::Locales->locale_info($locale);
+ my $language_name = $locale_info{'name'};
+
+ my $self = { conf => FS::Conf->new({ locale => $locale }),
+ csv => Text::CSV_XS->new({ binary => 1 }),
inbound => ($opt{'inbound'} ? 1 : 0),
buffer => ($opt{'buffer'} || []),
- };
+ _lh => FS::L10N->get_handle($locale),
+ _dh => eval { Date::Language->new($language_name) } ||
+ Date::Language->new()
+ };
bless $self, $class;
}
=head1 METHODS
+=over 4
+
=item inbound VALUE
Set/get the 'inbound' flag.
$self->{inbound};
}
+=item phonenum VALUE
+
+Set/get the locally meaningful phone number. This is used to tag call details
+for presentation on certain kinds of invoices.
+
+=cut
+
+sub phonenum {
+ my $self = shift;
+ $self->{phonenum} = shift if @_;
+ $self->{phonenum};
+}
+
=item append CDRS
Takes any number of call detail records (as L<FS::cdr> objects),
my $self = shift;
FS::cust_bill_pkg_detail->new(
- { 'format' => 'C', 'detail' => $self->header_detail }
+ { 'format' => 'C', 'detail' => $self->mt($self->header_detail) }
)
}
By default, this maps the following fields from the CDR:
+acctid => acctid
rated_price => amount
rated_classnum => classnum
rated_seconds => duration
accountcode => accountcode
startdate => startdate
+'phonenum' is set to the internal C<phonenum> value set on the formatter
+object.
+
It then calls C<columns> on the CDR to obtain a list of detail
columns, formats them as a CSV string, and stores that in the
'detail' field.
die "$me error combining ".$self->csv->error_input."\n"
if !$status;
- my $rated_price = $cdr->rated_price;
- $rated_price = 0 if $cdr->freesidestatus eq 'no-charge';
+ my $object = $self->{inbound} ? $cdr->cdr_termination(1) : $cdr;
+ my $price = $object->rated_price if $object;
+ $price = 0 if $cdr->freesidestatus eq 'no-charge';
FS::cust_bill_pkg_detail->new( {
- 'amount' => $rated_price,
+ 'acctid' => $cdr->acctid,
+ 'amount' => $price,
'classnum' => $cdr->rated_classnum,
'duration' => $cdr->rated_seconds,
'regionname' => $cdr->rated_regionname,
'startdate' => $cdr->startdate,
'format' => 'C',
'detail' => $self->csv->string,
+ 'phonenum' => $self->phonenum,
});
}
$self->{money_char} ||= ($self->conf->config('money_char') || '$');
}
+# localization methods
+
+sub time2str_local {
+ my $self = shift;
+ $self->{_dh}->time2str(@_);
+}
+
+sub mt {
+ my $self = shift;
+ $self->{_lh}->maketext(@_);
+}
+
#imitate previous behavior for now
sub duration {
my $cdr = shift;
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.