default to a session cookie instead of setting an explicit timeout, weird timezone...
[freeside.git] / FS / FS / cdr / broadsoft.pm
1 package FS::cdr::broadsoft;
2
3 =head1 NAME
4
5 FS::cdr::broadsoft - CDR parse module for Broadsoft
6
7 =head1 DESCRIPTION
8
9 Ref: BW-AccountingCDRInterfaceSpec-R22.pdf
10
11 =cut
12
13 use strict;
14 use base qw( FS::cdr );
15 use vars qw( %info );
16 use FS::cdr qw( _cdr_date_parser_maker _cdr_min_parser_maker );
17
18 %info = (
19   name     => 'Broadsoft',
20   weight   => 500,
21   header   => 1,
22   type     => 'csv',
23   sep_char => ',',
24   disabled => 0,
25
26   #deal with broadsoft's awful non-standard CSV escaping :/
27   row_callback => sub {
28     my $line = shift;
29     $line = qq("$line");       # put " at the beginning and end
30     $line =~ s/(?<!\\),/","/g; # all commas not after a \ become ","
31     $line =~ s/\\,/,/g;        # and now we can turn \, into ,
32     #XXX embedded \r and \n ?  none in my test data, and might be better to 
33     # leave escaped and deal with it from there?
34     $line =~ s/\\\\/\\/g;     # undo double backslashes?  none in my test data
35
36     #and now we have a properly formed CSV line
37     $line;
38   },
39
40   import_fields => [
41
42     # 1: recordId
43     # 2: serviceProvider
44     skip(2),
45
46     # 3: type
47     sub {
48       my ( $cdr, $data, $conf, $param ) = @_;
49       $param->{skiprow} = 1
50         if lc($data) ne 'normal';
51       '';
52     },
53
54     # 4: userNumber
55     # 5: groupNumber
56     skip(2),
57
58     # 6: direction
59     'dcontext',
60
61     # 7: callingNumber
62     trim('src'),
63
64     # 8: callingPresentationINdicator
65     skip(1),
66
67     # 9: calledNumber
68     trim('dst'),
69
70     # 10: startTime
71     _cdr_date_parser_maker('startdate'),
72
73     # 11: userTimeZone
74     skip(1),
75
76     # 12: answerIndicator
77     sub {
78       my( $cdr, $data ) = @_;
79       $cdr->disposition( $data =~ /^yes/i ? 'ANSWERED' : 'NO ANSWER');
80     },
81
82     # 13: answerTime
83     _cdr_date_parser_maker('answerdate'),
84
85     # 14: releaseTime
86     _cdr_date_parser_maker('enddate'),
87
88     # 15: terminationCause
89     # 16: networkType
90     # 17: carrierIdentificationCode
91     # 18: dialedDigits
92     # 19: callCategory
93     # 20: networkCallType
94     # 21: networkTranslatedNumber
95     # 22: networkTranslatedGroup
96     # 23: releasingParty
97     # 24: route
98     skip(10),
99
100     # 25: networkCallID
101     'sipcallid',
102
103     # 26: codedc
104     # 27: accessDeviceAddress
105     # 28: accessCallID
106     # 29: spare
107     # 30: failoverCorrelationId
108     # 31: spare
109     # 32: group
110     # 33: department
111     skip(8),
112
113     # 34: accountCode
114     'accountcode',
115
116     # 35: authorizationCode
117     # 36: originalCalledNumber
118     # 37: originalCalledPresentationIndicator
119     # 38: originalCalledReason
120     # 39: redirectingNumber
121     # 40: redirectingPresentationIndicator
122     # 41: redirectingReason
123     # 42: chargeIndicator
124     # 43: typeOfNetwork
125     # 44: voicePortalCalling.invocationTime
126     # 45: localCallId
127     # 46: remoteCallId
128     # 47: callingPartyCategory
129     #
130     # Also... cols 48 - 448 see Broadsoft documentation
131     skip(87), #35-121 inclusive
132
133     #122: otherPartyName
134     'clid',
135
136     #123: otherPartyNamePresentationIndicator
137     sub {
138       my( $cdr, $data ) = @_;
139       $cdr->clid( $data ) unless $data =~ /^Public$/i;
140     },
141
142     skip(22), #124-145 inclusive
143
144     # 146: chargedNumber
145     'charged_party',
146
147   ],
148
149 );
150
151 sub trim {
152   my $fieldname = shift;
153   return sub {
154     my($cdr, $data) = @_;
155     $data =~ s/^\+1//;
156     $cdr->$fieldname($data);
157     ''
158   }
159 }
160
161 sub skip {
162   map { undef } (1..$_[0]);
163 }
164
165 1;
166
167 __END__
168
169 list of freeside CDR fields, useful ones marked with *
170
171            acctid - primary key
172     *[1]   calldate - Call timestamp (SQL timestamp)
173            clid - Caller*ID with text
174 7   *      src - Caller*ID number / Source number
175 9   *      dst - Destination extension
176            dcontext - Destination context
177            channel - Channel used
178            dstchannel - Destination channel if appropriate
179            lastapp - Last application if appropriate
180            lastdata - Last application data
181 10  *      startdate - Start of call (UNIX-style integer timestamp)
182 13         answerdate - Answer time of call (UNIX-style integer timestamp)
183 14  *      enddate - End time of call (UNIX-style integer timestamp)
184     *      duration - Total time in system, in seconds
185     *      billsec - Total time call is up, in seconds
186 12  *[2]   disposition - What happened to the call: ANSWERED, NO ANSWER, BUSY
187            amaflags - What flags to use: BILL, IGNORE etc, specified on a per
188            channel basis like accountcode.
189 4   *[3]   accountcode - CDR account number to use: account
190            uniqueid - Unique channel identifier
191            userfield - CDR user-defined field
192            cdr_type - CDR type - see FS::cdr_type (Usage = 1, S&E = 7, OC&C = 8)
193     *[4]   charged_party - Service number to be billed
194            upstream_currency - Wholesale currency from upstream
195     *[5]   upstream_price - Wholesale price from upstream
196            upstream_rateplanid - Upstream rate plan ID
197            rated_price - Rated (or re-rated) price
198            distance - km (need units field?)
199            islocal - Local - 1, Non Local = 0
200     *[6]   calltypenum - Type of call - see FS::cdr_calltype
201            description - Description (cdr_type 7&8 only) (used for
202            cust_bill_pkg.itemdesc)
203            quantity - Number of items (cdr_type 7&8 only)
204            carrierid - Upstream Carrier ID (see FS::cdr_carrier)
205            upstream_rateid - Upstream Rate ID
206            svcnum - Link to customer service (see FS::cust_svc)
207            freesidestatus - NULL, done (or something)
208
209 [1] Auto-populated from startdate if not present
210 [2] Package options available to ignore calls without a specific disposition
211 [3] When using 'cdr-charged_party-accountcode' config
212 [4] Auto-populated from src (normal calls) or dst (toll free calls) if not present
213 [5] When using 'upstream_simple' rating method.
214 [6] Set to usage class classnum when using pre-rated CDRs and usage class-based
215     taxation (local/intrastate/interstate/international)