RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / part_export / phone_sqlradius.pm
1 package FS::part_export::phone_sqlradius;
2
3 use vars qw(@ISA $DEBUG %info );
4 use Tie::IxHash;
5 use FS::Record qw( dbh str2time_sql ); #qsearch qsearchs );
6 #use FS::part_export;
7 use FS::part_export::sqlradius qw(sqlradius_connect);
8 #use FS::svc_phone;
9 #use FS::export_svc;
10 #use Carp qw( cluck );
11
12 @ISA = qw(FS::part_export::sqlradius);
13
14 $DEBUG = 0;
15
16 tie %options, 'Tie::IxHash',
17   'datasrc'  => { label=>'DBI data source ' },
18   'username' => { label=>'Database username' },
19   'password' => { label=>'Database password' },
20   'ignore_accounting' => {
21     type  => 'checkbox',
22     label => 'Ignore accounting records from this database'
23   },
24   'hide_ip' => {
25     type  => 'checkbox',
26     label => 'Hide IP address information on session reports',
27   },
28   'hide_data' => {
29     type  => 'checkbox',
30     label => 'Hide download/upload information on session reports',
31   },
32
33   #should be default for this one, right?
34   #'show_called_station' => {
35   #  type  => 'checkbox',
36   #  label => 'Show the Called-Station-ID on session reports',
37   #},
38
39 ;
40
41 %info = (
42   'svc'        => 'svc_phone',
43   'desc'       => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS) for phone provisioning and rating',
44   'options'    => \%options,
45   'no_machine' => 1,
46   'notes'      => <<END,
47 Real-time export of <b>radcheck</b> table
48 to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a>
49 or <a href="http://radius.innercite.com/">ICRADIUS</a>.
50 <br><br>
51
52 This export is for phone/VoIP provisioning and rating.  For a regular RADIUS
53 export, see sqlradius.
54 <br><br>
55
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
59 Freeside database.
60 <br><br>
61 -->
62
63 See the
64 <a href="http://search.cpan.org/dist/DBI/DBI.pm#connect">DBI documentation</a>
65 and the
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.
68
69 END
70 );
71
72 sub rebless { shift; }
73
74 sub export_username {
75   my($self, $svc_phone) = (shift, shift);
76   $svc_phone->countrycode. $svc_phone->phonenum;
77 }
78
79 sub _export_suspend {}
80 sub _export_unsuspend {}
81
82 #probably harmless that we ->can('usage_sessions').... ?
83
84 #we want to feed these into CDRs, not update svc_acct records
85 sub update_svc {
86   my $self = shift;
87
88   my $fdbh = dbh;
89   my $dbh = sqlradius_connect( map $self->option($_),
90                                    qw( datasrc username password ) );
91
92   my $str2time = str2time_sql( $dbh->{Driver}->{Name} );
93
94   my @fields = qw( radacctid username realm acctsessiontime );
95
96   my @param = ();
97   my $where = '';
98
99   my $sth = $dbh->prepare("
100     SELECT RadAcctId, UserName, AcctSessionTime,
101            $str2time AcctStartTime),  $str2time AcctStopTime), 
102            CallingStationID, CalledStationID
103       FROM radacct
104       WHERE FreesideStatus IS NULL
105         AND AcctStopTime != 0
106   ") or die $dbh->errstr;
107   $sth->execute() or die $sth->errstr;
108
109   while ( my $row = $sth->fetchrow_arrayref ) {
110     my( $RadAcctId, $UserName, $AcctSessionTime,
111         $AcctStartTime, $AcctStopTime, 
112         $CallingStationID, $CalledStationID,
113       )= @$row;
114     warn "processing record: ".
115          "$RadAcctId ($UserName for ${AcctSessionTime}s"
116       if $DEBUG;
117
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
120
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,
129     };
130
131     my $errinfo = "for RADIUS detail RadAcctID $RadAcctId ".
132                   "(UserName $UserName)";
133
134     my $error = $cdr->insert;
135     my $status = $error ? 'skipped' : 'done';
136
137     warn "setting FreesideStatus to $status $errinfo\n" if $DEBUG; 
138     my $psth = $dbh->prepare("UPDATE radacct
139                                 SET FreesideStatus = ?
140                                 WHERE RadAcctId = ?"
141     ) or die $dbh->errstr;
142     $psth->execute($status, $RadAcctId) or die $psth->errstr;
143
144     $fdbh->commit or die $fdbh->errstr if $oldAutoCommit;
145
146   }
147
148 }
149
150 1;
151