summaryrefslogtreecommitdiff
path: root/FS/FS/cdr/u4.pm
blob: bf5e18225ce782d14f46228a0814dc7d3cefc676 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package FS::cdr::u4;

use strict;
use vars qw(@ISA %info);
use FS::cdr qw(_cdr_date_parser_maker);

@ISA = qw(FS::cdr);

# About the ANI/DNIS/*Number columns:
# For inbound calls, ANI appears to be the true source number.
# Usually ANI = TermNumber in that case.  (Case 1a.)
# In a few inbound CDRs, ANI = OrigNumber, the BillToNumber is also 
# the DialedNumber and DNIS (and always an 800 number), and the TermNumber 
# is a different number.  (Case 2; rare.)
#
# For outbound calls, DNIS is always empty.  The TermNumber appears to
# be the true destination.  The DialedNumber may be empty (Case 1b), or
# equal the TermNumber (Case 3), or be a different number (Case 4; this 
# probably shows routing to a different destination).
#
# How we are handling them:
# Case 1a (inbound): src = ANI, dst = BillToNumber
# Case 1b (outbound): src = BillToNumber, dst = ANI
# Case 2: src = ANI, dst = DialedNumber, dst_term = TermNumber
# Case 3: src = BillToNumber, dst = DialedNumber
# Case 4: src = BillToNumber, dst = DialedNumber, dst_term = TermNumber

%info = (
  'name'          => 'U4',
  'weight'        => 490,
  'type'          => 'fixedlength',
  'fixedlength_format' => [qw(
    CDRType:3:1:3
    MasterAccountID:12:4:15
    SubAccountID:12:16:27
    BillToNumber:18:28:45
    AccountCode:12:46:57
    CallDateStartTime:14:58:71
    TimeOfDay:1:72:72
    CalculatedSeconds:12:73:84
    City:30:85:114
    State:2:115:116
    Country:40:117:156
    Charges:21:157:177
    CallDirection:1:178:178
    CallIndicator:1:179:179
    ReportIndicator:1:180:180
    ANI:10:181:190
    DNIS:10:191:200
    PIN:16:201:216
    OrigNumber:10:217:226
    TermNumber:10:227:236
    DialedNumber:18:237:254
    DisplayNumber:18:255:272
    RecordSource:1:273:273
    LECInfoDigits:2:274:275
    OrigNPA:4:276:279
    OrigNXX:5:280:284
    OrigLATA:3:285:287
    OrigZone:1:288:288
    OrigCircuit:12:289:300
    OrigTrunkGroupCLLI:12:301:312
    TermNPA:4:313:316
    TermNXX:5:317:321
    TermLATA:3:322:324
    TermZone:1:325:325
    TermCircuit:12:326:337
    TermTrunkGroupCLLI:12:338:349
    TermOCN:5:350:354
  )],
  # at least that's how they're defined in the spec we have.
  # the real CDRs have several differences.
  'import_fields' => [
    '',               #CDRType (for now always 'V')
    '',               #MasterAccountID
    '',               #SubAccountID
    'charged_party',  #BillToNumber
    'accountcode',    #AccountCode
    _cdr_date_parser_maker('startdate'),
                      #CallDateTime
    '',               #TimeOfDay (always 'S')
    sub {             #CalculatedSeconds
      my($cdr, $sec) = @_;
      $cdr->duration($sec);
      $cdr->billsec($sec);
    },
    '',               #City
    '',               #State
    '',               #Country
    'upstream_price', #Charges
    sub {             #CallDirection
      my ($cdr, $dir) = @_;
      $cdr->set('direction', $dir);
      if ( $dir eq 'O' ) {
        $cdr->set('src', $cdr->charged_party);
      } elsif ( $dir eq 'I' ) {
        $cdr->set('dst', $cdr->charged_party);
      }
    },
    '',               #CallIndicator  #calltype?
    '',               #ReportIndicator
    sub {             #ANI
      # For inbound calls, this is the source.
      # For outbound calls it's sometimes the destination but TermNumber 
      # is more reliable.
      my ($cdr, $number) = @_;
      if ( $cdr->direction eq 'I' ) {
        $cdr->set('src', $number);
      }
    },
    '',               #DNIS
    '',               #PIN
    '',               #OrigNumber
    sub {             #TermNumber
      # For outbound calls, this is the terminal destination (after call 
      # routing).  It's sometimes also the dialed destination (Case 1b and 3).
      my ($cdr, $number) = @_;
      if ( $cdr->direction eq 'O' ) {
        $cdr->set('dst_term', $number);
        $cdr->set('dst', $number); # change this later if Case 4
      }
    },
    sub {             #DialedNumber
      my ($cdr, $number) = @_;
      # For outbound calls, this is the destination before any call routing,
      # and should be used for billing.  Except when it's null; then use 
      # the TermNumber.
      if ( $cdr->direction eq 'O' and $number =~ /\d/ ) {
        # Case 4
        $cdr->set('dst', $number);
      }
    },

    '',               #DisplayNumber
    '',               #RecordSource
    '',               #LECInfoDigits
    ('') x 13,
  ],
);

# Case 1a (inbound): src = ANI, dst = BillToNumber
# Case 1b (outbound): src = BillToNumber, dst = TermNumber
# Case 2: src = ANI, dst = DialedNumber, dst_term = TermNumber
# Case 3: src = BillToNumber, dst = TermNumber
# Case 4: src = BillToNumber, dst = DialedNumber, dst_term = TermNumber

1;