5 use Date::Parse 'str2time';
6 use Date::Format 'time2str';
7 use FS::UID qw(adminsuidsetup dbh);
8 use FS::Record qw(qsearchs);
14 getopts('H:U:P:D:T:vs:e:', \%opt);
15 my $user = shift or die &usage;
17 my $dsn = 'dbi:mysql';
18 $dsn .= ":database=$opt{D}" if $opt{D};
19 $dsn .= ":host=$opt{H}" if $opt{H};
21 my $mysql = DBI->connect($dsn, $opt{U}, $opt{P})
25 $FS::UID::AutoCommit = 0;
26 my $fsdbh = FS::UID::dbh;
28 # don't use freesidestatus
35 my $last_cdr = qsearchs({
38 'extra_sql' => 'ORDER BY cdrid DESC LIMIT 1',
40 $start_id = $last_cdr ? $last_cdr->cdrid + 1: 1;
43 print "Selecting CDRs from $start_id to ".($end_id || 'end')."...\n";
45 my $table = $opt{T} || 'call_history';
46 # spelled "disposion" in the table
48 id extension_number flow channel partyid start answer duration disposion did
50 my $sql = 'SELECT '.join(',', @cols). " FROM $table WHERE id >= $start_id";
51 $sql .= " AND id <= $end_id" if $end_id;
52 $sql .= " ORDER BY id";
53 my $sth = $mysql->prepare($sql);
55 print "Importing ".$sth->rows." records...\n";
57 my $cdr_batch = new FS::cdr_batch({
58 'cdrbatch' => 'mysql-import-'. time2str('%Y/%m/%d-%T',time),
60 my $error = $cdr_batch->insert;
62 my $cdrbatchnum = $cdr_batch->cdrbatchnum;
68 while ( $row = $sth->fetchrow_hashref ) {
69 if ( $opt{s} # skip this check if the range doesn't overlap
70 and qsearchs('cdr', { cdrid => $row->{id} } ) ) {
72 print $row->{id} ." (skipped)\n" if $opt{v};
75 my $cdr = FS::cdr->new({
77 channel => $row->{channel},
78 duration => $row->{duration},
79 billsec => $row->{duration},
80 disposition => $row->{disposion},
81 startdate => str2time($row->{start}),
82 answerdate => str2time($row->{answer}),
83 cdrbatchnum => $cdrbatchnum,
84 accountcode => $row->{client_client_id},
87 print $row->{id},"\n" if $opt{v};
88 if ( $row->{flow} eq 'out' ) {
89 $cdr->src($row->{'extension_number'});
90 $cdr->dst($row->{'partyid'});
92 elsif ( $row->{flow} eq 'in' ) {
93 $cdr->dst($row->{'did'});
94 $cdr->src($row->{'partyid'});
98 die $row->{id} .": invalid flow value: '".$row->{flow}."'\n";
100 my $error = $cdr->insert;
103 die $row->{id} . ": failed import: $error\n";
105 $first ||= $row->{id};
109 $fsdbh->commit or die $fsdbh->errstr;
111 print "Imported $imported CDRs ($first - $last).\n" if $imported;
112 print "Skipped $skipped duplicates.\n" if $skipped;
116 "Usage: \n cdr-voipnow.import\n\t[ -H host ]\n\t-D database\n\t-U user\n\t-P password\n\t[ -v ] [ -s start ] [ -e end ]\n\tfreesideuser\n";
121 cdr-voipnow.import - Import call data records (CDRs) from a 4psa VoipNow system
125 cdr-voipnow.import [ -H host ] -D database -U user -P password
126 [ -v ] [ -s start ] [ -e end ] freesideuser
130 Connects to a MySQL database and downloads CDRs from the "call_history" table.
131 The "id" field maps to "cdrid" in Freeside. Other than that, the following
132 fields are imported: channel, duration, billsec, startdate, answerdate,
133 disposition, src, dst. src and dst are inferred from the "extension_number"
134 and "partyid" fields, with the value of the "flow" field (in or out) deciding
135 which is the source number and which is the destination.
137 Any import errors (except duplicates) will abort and roll back the
142 -H, -D, -U, -P: parameters to connect to the database: host, database name
143 user, password. Required, except -H, which defaults to localhost.
145 -s: set the lowest CDR id to import. By default, the script will find
146 the highest existing cdrid and import all CDRs with ids greater than that.
147 -s overrides this and turns on duplicate checking.
149 -e: set the highest CDR id to import. By default, this is unlimited.
151 -v: report all CDR ids as they are imported.