1 package FS::part_export::phone_sqlradius;
3 use vars qw(@ISA $DEBUG %info );
5 use FS::Record qw( dbh str2time_sql ); #qsearch qsearchs );
7 use FS::part_export::sqlradius qw(sqlradius_connect);
10 #use Carp qw( cluck );
12 @ISA = qw(FS::part_export::sqlradius);
16 tie %options, 'Tie::IxHash',
17 'datasrc' => { label=>'DBI data source ' },
18 'username' => { label=>'Database username' },
19 'password' => { label=>'Database password' },
20 'ignore_accounting' => {
22 label => 'Ignore accounting records from this database'
26 label => 'Hide IP address information on session reports',
30 label => 'Hide download/upload information on session reports',
33 #should be default for this one, right?
34 #'show_called_station' => {
36 # label => 'Show the Called-Station-ID on session reports',
43 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS) for phone provisioning and rating',
44 'options' => \%options,
46 Real-time export of <b>radcheck</b> table
47 <!--, <b>radreply</b> and <b>usergroup</b>-- tables>
48 to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a>
49 or <a href="http://radius.innercite.com/">ICRADIUS</a>.
52 This export is for phone/VoIP provisioning and rating. For a regular RADIUS
53 export, see sqlradius.
56 <!--An existing RADIUS database will be updated in realtime, but you can use
57 <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation:Developer/bin/freeside-phone_sqlradius-reset">freeside-phone_sqlradius-reset</a>
58 to delete the entire RADIUS database and repopulate the tables from the
64 <a href="http://search.cpan.org/dist/DBI/DBI.pm#connect">DBI documentation</a>
66 <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a>
67 for the exact syntax of a DBI data source.
72 sub rebless { shift; }
75 my($self, $svc_phone) = (shift, shift);
76 $svc_phone->countrycode. $svc_phone->phonenum;
79 sub _export_suspend {}
80 sub _export_unsuspend {}
82 #probably harmless that we ->can('usage_sessions').... ?
84 #we want to feed these into CDRs, not update svc_acct records
89 my $dbh = sqlradius_connect( map $self->option($_),
90 qw( datasrc username password ) );
92 my $str2time = str2time_sql( $dbh->{Driver}->{Name} );
94 my @fields = qw( radacctid username realm acctsessiontime );
99 my $sth = $dbh->prepare("
100 SELECT RadAcctId, UserName, AcctSessionTime,
101 $str2time AcctStartTime), $str2time AcctStopTime),
102 CallingStationID, CalledStationID
104 WHERE FreesideStatus IS NULL
105 AND AcctStopTime != 0
106 ") or die $dbh->errstr;
107 $sth->execute() or die $sth->errstr;
109 while ( my $row = $sth->fetchrow_arrayref ) {
110 my( $RadAcctId, $UserName, $AcctSessionTime,
111 $AcctStartTime, $AcctStopTime,
112 $CallingStationID, $CalledStationID,
114 warn "processing record: ".
115 "$RadAcctId ($UserName for ${AcctSessionTime}s"
118 my $oldAutoCommit = $FS::UID::AutoCommit; # can't undo side effects, but at
119 local $FS::UID::AutoCommit = 0; # least we can avoid over counting
121 my $cdr = new FS::cdr {
122 'src' => $CallingStationID,
123 'charged_party' => $UserName,
124 'dst' => $CalledStationID,
125 'startdate' => $AcctStartTime,
126 'enddate' => $AcctStopTime,
127 'duration' => $AcctStopTime - $AcctStartTime,
128 'billsec' => $AcctSessionTime,
131 my $errinfo = "for RADIUS detail RadAcctID $RadAcctId ".
132 "(UserName $UserName)";
134 my $error = $cdr->insert;
135 my $status = $error ? 'skipped' : 'done';
137 warn "setting FreesideStatus to $status $errinfo\n" if $DEBUG;
138 my $psth = $dbh->prepare("UPDATE radacct
139 SET FreesideStatus = ?
141 ) or die $dbh->errstr;
142 $psth->execute($status, $RadAcctId) or die $psth->errstr;
144 $fdbh->commit or die $fdbh->errstr if $oldAutoCommit;