AAPT call details format, stage 1, #27139
authorMark Wells <mark@freeside.biz>
Thu, 23 Jan 2014 01:25:06 +0000 (17:25 -0800)
committerMark Wells <mark@freeside.biz>
Thu, 23 Jan 2014 01:25:06 +0000 (17:25 -0800)
FS/FS/Record.pm
FS/FS/cdr.pm
FS/FS/cdr/aapt.pm [new file with mode: 0644]

index 39a3920..ff8a0cc 100644 (file)
@@ -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";
     }
 
index 5658be9..80b31bf 100644 (file)
@@ -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 (file)
index 0000000..600a192
--- /dev/null
@@ -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;