From: Mark Wells Date: Thu, 23 Jan 2014 01:25:06 +0000 (-0800) Subject: AAPT call details format, stage 1, #27139 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=8edb7f0ed92d28c935a8e2c26b5b645dccc7704e;hp=da1188b39e62d48f5dca496ee7415189bd037219 AAPT call details format, stage 1, #27139 --- diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 39a392013..ff8a0cc27 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -1849,7 +1849,7 @@ sub batch_import { my( $type, $header, $sep_char, $fixedlength_format, $xml_format, $asn_format, - $row_callback, @fields ); + $parser_opt, $row_callback, @fields ); my $postinsert_callback = ''; $postinsert_callback = $param->{'postinsert_callback'} @@ -1882,6 +1882,11 @@ sub batch_import { ? $param->{'format_fixedlength_formats'}{ $param->{'format'} } : ''; + $parser_opt = + $param->{'format_parser_opts'} + ? $param->{'format_parser_opts'}{ $param->{'format'} } + : {}; + $xml_format = $param->{'format_xml_formats'} ? $param->{'format_xml_formats'}{ $param->{'format'} } @@ -1936,18 +1941,17 @@ sub batch_import { if ( $type eq 'csv' ) { - my %attr = ( 'binary' => 1, ); - $attr{sep_char} = $sep_char if $sep_char; - $parser = new Text::CSV_XS \%attr; + $parser_opt->{'binary'} = 1; + $parser_opt->{'sep_char'} = $sep_char if $sep_char; + $parser = Text::CSV_XS->new($parser_opt); } elsif ( $type eq 'fixedlength' ) { eval "use Parse::FixedLength;"; die $@ if $@; - $parser = Parse::FixedLength->new($fixedlength_format); + $parser = Parse::FixedLength->new($fixedlength_format, $parser_opt); - } - else { + } else { die "Unknown file type $type\n"; } diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm index 5658be94b..80b31bfb9 100644 --- a/FS/FS/cdr.pm +++ b/FS/FS/cdr.pm @@ -1657,9 +1657,15 @@ my %import_options = ( keys %cdr_info }, - 'format_row_callbacks' => { map { $_ => $cdr_info{$_}->{'row_callback'}; } - keys %cdr_info - }, + 'format_row_callbacks' => + { map { $_ => $cdr_info{$_}->{'row_callback'}; } + keys %cdr_info + }, + + 'format_parser_opts' => + { map { $_ => $cdr_info{$_}->{'parser_opt'}; } + keys %cdr_info + }, ); sub _import_options { diff --git a/FS/FS/cdr/aapt.pm b/FS/FS/cdr/aapt.pm new file mode 100644 index 000000000..600a1920f --- /dev/null +++ b/FS/FS/cdr/aapt.pm @@ -0,0 +1,126 @@ +package FS::cdr::aapt; + +use strict; +use base qw( FS::cdr ); +use vars qw ( %info ); +use FS::cdr qw(_cdr_date_parser_maker); + +my %CURRENCY = ( #Table 2.1.3 + 1 => 'AUD', + 2 => 'USD', + 3 => 'AUD', +); + +my %UNIT_SCALE = ( #Table 2.1.4 + 100 => 1, # seconds + 101 => 0.1, # tenths + 120 => 60, # minutes + 130 => 3600, # hours + #(irrelevant, because we don't yet support these usage types, but still) + 200 => 1, # bytes + 201 => 2**10, # KB + 202 => 2**20, # MB + 203 => 2**30, # GB + 401 => 2**10 * 1000, # "decimal MB" + 402 => 2**20 * 1000, # "decimal GB" + 451 => 1, # Kbps--conveniently the same as our base unit + 452 => 1000, # Mbps (decimal) +); + +%info = ( + 'name' => 'AAPT CTOP', + 'weight' => 600, + 'header' => 1, + 'type' => 'fixedlength', + 'row_callback' => sub { $DB::single = 1; }, #XXX + 'parser_opt' => { trim => 1 }, + 'fixedlength_format' => [qw( + record_type:6:1:6 + transaction_id:20R:7:26 + product_id:6R:27:32 + usage_type:6R:33:38 + id_type:6R:39:44 + id_value:48R:45:92 + trans_time:14:93:106 + sec_time:14:107:120 + target:24R:121:144 + origin:24R:145:168 + rated_units:10R:169:178 + rated_price:18R:179:196 + jurisdiction:18R:197:214 + fnn:18R:215:232 + foreign_amount:18R:233:250 + currency:6R:251:256 + recipient:10R:257:266 + completion:3R:267:269 + record_id:22R:270:291 + raw_units:10R:292:301 + raw_unittype:6R:302:307 + rated_unittype:6R:308:313 + base_amount:18R:314:331 + second_units:10R:332:341 + third_units:10R:342:351 + special1:255:352:606 + special2:96:607:702 + service_type:6:703:708 + sec_id_type:6:709:714 + sec_id_value:48:715:762 + unused:238:763:1000 + )], + 'import_fields' => [ + sub { # record type + my ($cdr, $data, $conf, $param) = @_; + $param->{skiprow} = 1 if $data ne 'PWTDET'; # skip non-detail records + }, + '', # transaction ID + '', # product ID (CPRD) + 'calltypenum', # usage ID (CUSG) + sub { # ID type + my ($cdr, $data, $conf, $param) = @_; + if ($data != 1) { + warn "AAPT: service ID type is not telephone number.\n"; + $param->{skiprow} = 1; + } + }, + 'charged_party', # ID value (phone number, if ID type = 1) + _cdr_date_parser_maker('startdate'), # trans date/time + '', # secondary date (unused?) + 'dst', # Target (B-party) + 'src', # Origin (A-party) + 'billsec', # Rated units (may need unit scaling) + sub { # Amount charged + my ($cdr, $data) = @_; + $cdr->set('upstream_price', sprintf('%.5f', $data/100)); + }, + 'dcontext', # Jurisdiction code; we use dcontext for this + '', # Full National Number (unused?) + '', # "Foreign Amount" + sub { # Currency + my ($cdr, $data) = @_; + $cdr->set('upstream_currency', $CURRENCY{$data}); + }, + '', # Reseller account number + '', # Completion status + 'uniqueid', # CTOP Record ID + 'duration', # Raw units + sub { # Raw unit type + my ($cdr, $data) = @_; + if (exists($UNIT_SCALE{$data})) { + $cdr->set('duration', + sprintf('%.0f', $cdr->get('duration') * $UNIT_SCALE{$data}) + ); + } + }, + sub { # Rated unit type + my ($cdr, $data) = @_; + if (exists($UNIT_SCALE{$data})) { + $cdr->set('billsec', + sprintf('%.0f', $cdr->get('billsec') * $UNIT_SCALE{$data}) + ); + } + }, + # trailing fields we don't care about + ], #import_fields +); + +1;