5 use Date::Format 'time2str';
6 use Date::Parse 'str2time';
9 use Net::HTTPS::Any qw(https_post);
11 use FS::Record qw(qsearchs dbh);
12 use FS::UID qw(adminsuidsetup);
16 freeside-cdr-portaone-import -h 'your.domain.com:443' -u switchusername -p switchpass
17 [-s startdate] [-e enddate] [-v] freesideuser
21 my ($host,$username,$password,$startdate,$enddate,$verbose);
23 "enddate=s" => \$enddate,
25 "password=s" => \$password,
26 "startdate=s" => \$startdate,
27 "username=s" => \$username,
28 "verbose" => \$verbose,
31 my $fsuser = $ARGV[-1];
33 die usage() unless $host && $password && $username && $fsuser;
35 adminsuidsetup($fsuser);
38 if ($host =~ /^(.*)\:(.*)$/) {
44 $startdate = str2time($startdate) or die "Can't parse startdate $startdate";
45 $startdate = time2str("%Y-%m-%d %H:%M:%S",$startdate);
48 my $lastbatch = qsearchs({
49 'table' => 'cdr_batch',
50 'hashref' => { 'cdrbatch' => {op=>'like', value=>'portaone-import%'}},
51 'order_by' => 'ORDER BY _date DESC LIMIT 1',
53 $startdate = time2str("%Y-%m-%d %H:%M:%S", $lastbatch->_date + 1) if $lastbatch;
55 $startdate ||= '2010-01-01 00:00:00'; #seems decently in the past
59 $enddate = str2time($enddate) or die "Can't parse enddate $enddate";
61 $enddate = time2str("%Y-%m-%d %H:%M:%S",$enddate);
63 $enddate ||= time2str("%Y-%m-%d %H:%M:%S",$now);
65 print "Downloading records from $startdate to $enddate\n" if $verbose;
67 my $auth_info; # needs to be declared undef for call_api
68 $auth_info = call_api('Session','login',{
70 'password' => $password,
74 my $custlist = call_api('Customer','get_customer_list');
75 my @custnum = map { $_->{'i_customer'} } @{$custlist->{'customer_list'}};
76 foreach my $custnum (@custnum) {
77 print "Processing customer $custnum\n" if $verbose;
78 my $xdrs = call_api('Customer','get_customer_xdrs',{
79 'i_customer' => $custnum,
80 'from_date' => $startdate,
81 'to_date' => $enddate,
82 'cdr_entity' => 'C', # can also be 'A', or blank for both
84 my @xdrs = @{$xdrs->{'xdr_list'}};
85 print scalar(@xdrs) . " xdrs retrieved\n" if $verbose;
86 $results->{$custnum} = \@xdrs;
89 call_api('Session','logout',$auth_info);
91 $FS::UID::AutoCommit = 0;
93 my $cdr_batch = new FS::cdr_batch({
94 'cdrbatch' => 'portaone-import-'. time2str('%Y/%m/%d-%T',$now),
97 my $error = $cdr_batch->insert;
100 die "Error inserting batch: $error";
103 foreach my $custnum (keys %$results) {
104 foreach my $xdr (@{$results->{$custnum}}) {
105 my $cdr = FS::cdr->new ({
106 'cdrbatchnum' => $cdr_batch->cdrbatchnum,
107 'acctid' => $xdr->{'i_xdr'}, #???
108 'accountcode' => $xdr->{'account_id'}, #???
109 'startdate' => $xdr->{'unix_connect_time'},
110 'enddate' => $xdr->{'unix_disconnect_time'},
112 ### XXX NEED TO MAP FIELDS:
113 #i_xdr int The unique ID of the xdr record
114 #account_id int The unique ID of the account database record
115 #CLI string Calling Line Identification
116 #CLD string Called Line Identification
117 #charged_amount float Amount charged
118 #charged_quantity int Units charged
119 #country string Country
120 #subdivision string Country subdivision
121 #description string Destination description
122 #disconnect_cause string The code of disconnect cause
123 #bill_status string Call bill status
124 #disconnect_reason string Call disconnect reason
125 #connect_time dateTime Call connect time
126 #unix_connect_time int Call connect time (expressed in Unix time format - seconds since epoch)
127 #disconnect_time dateTime Call disconnect time
128 #unix_disconnect_time int Call disconnect time i_xdr int The unique ID of the xdr record
129 #account_id int The unique ID of the account database record
130 #CLI string Calling Line Identification
131 #CLD string Called Line Identification
132 #charged_amount float Amount charged
133 #charged_quantity int Units charged
134 #country string Country
135 #subdivision string Country subdivision
136 #description string Destination description
137 #disconnect_cause string The code of disconnect cause
138 #bill_status string Call bill status
139 #disconnect_reason string Call disconnect reason
140 #connect_time dateTime Call connect time
141 #unix_connect_time int Call connect time (expressed in Unix time format - seconds since epoch)
142 #disconnect_time dateTime Call disconnect time
143 #unix_disconnect_time int Call disconnect time (expressed in Unix time format - seconds since epoch)
144 #bill_time dateTime Call bill time
145 #bit_flags int Extended information how the service was used; the integer field that should be treated as a bit-map. Each currently used bit is listed in the Transaction_Flag_Types table (bit_offset indicates position)
146 #call_recording_url string Path to recorded .wav files
147 #call_recording_server_url string URL to the recording server (expressed in Unix time format - seconds since epoch)
148 #bill_time dateTime Call bill time
149 #bit_flags int Extended information how the service was used; the integer field that should be treated as a bit-map. Each currently used bit is listed in the Transaction_Flag_Types table (bit_offset indicates position)
150 #call_recording_url string Path to recorded .wav files
151 #call_recording_server_url string URL to the recording server
154 $error = $cdr->insert;
157 die "Error inserting cdr: $error";
167 my ($service,$method,$params) = @_;
168 my %auth_info = $auth_info ? ('auth_info' => encode_json($auth_info)) : ();
170 print "Calling $service/$method...\n" if $verbose;
171 my ( $page, $response, %reply_headers ) = https_post(
174 'path' => '/rest/'.$service.'/'.$method.'/',
175 'args' => [ %auth_info, 'params' => encode_json($params) ],
177 return decode_json($page) if $response eq '200 OK';
178 if ($response =~ /^500/) {
179 my $error = decode_json($page);
180 die "Server returned error during $service/$method: ".$error->{'faultstring'}
181 if $error->{'faultcode'};
183 die "Bad response from server during $service/$method: $response";