Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / FS / FS / part_pkg / sqlradacct_hour.pm
1 package FS::part_pkg::sqlradacct_hour;
2
3 use strict;
4 use vars qw(@ISA %info);
5 #use FS::Record qw(qsearch qsearchs);
6 use FS::part_pkg::flat;
7
8 @ISA = qw(FS::part_pkg::flat);
9
10 # some constants to facilitate changes
11 # maybe we display charge per petabyte in the future?
12 use constant KB => 1024;
13 use constant MB => KB * 1024;
14 use constant GB => MB * 1024;
15 use constant BU => GB;            # base unit
16 use constant BS => 'gigabyte';    # BU spelled out
17 use constant BA => 'gig';         # BU abbreviation
18
19 %info = (
20   'name' => 'Time and data charges from an SQL RADIUS radacct table',
21   'shortname' => 'Usage charges from RADIUS',
22   'inherit_fields' => [ 'global_Mixin' ],
23   'fields' => {
24     'recur_included_hours' => { 'name' => 'Hours included',
25                                 'default' => 0,
26                               },
27     'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
28                                'default' => 0,
29                              },
30     'recur_hourly_cap'    => { 'name' => 'Maximum overage charge for hours'.
31                                          ' (0 means no cap)',
32
33                                'default' => 0,
34                              },
35
36     'recur_included_input' => { 'name' => 'Upload ' . BS . 's included',
37                                 'default' => 0,
38                               },
39     'recur_input_charge' => { 'name' =>
40                                       'Additional charge per ' . BS . ' upload',
41                               'default' => 0,
42                             },
43     'recur_input_cap'    => { 'name' => 'Maximum overage charge for upload'.
44                                          ' (0 means no cap)',
45                                'default' => 0,
46                              },
47
48     'recur_included_output' => { 'name' => 'Download ' . BS . 's included',
49                                  'default' => 0,
50                               },
51     'recur_output_charge' => { 'name' =>
52                                      'Additional charge per ' . BS . ' download',
53                               'default' => 0,
54                             },
55     'recur_output_cap'    => { 'name' => 'Maximum overage charge for download'.
56                                          ' (0 means no cap)',
57                                'default' => 0,
58                              },
59
60     'recur_included_total' => { 'name' =>
61                                      'Total ' . BS . 's included',
62                                 'default' => 0,
63                               },
64     'recur_total_charge' => { 'name' =>
65                                'Additional charge per ' . BS . ' total',
66                               'default' => 0,
67                             },
68     'recur_total_cap'    => { 'name' => 'Maximum overage charge for total'.
69                                         ' ' . BS . 's (0 means no cap)',
70                                'default' => 0,
71                              },
72
73     'global_cap'         => { 'name' => 'Global cap on all overage charges'.
74                                         ' (0 means no cap)',
75                               'default' => 0,
76                             },
77
78   },
79   'fieldorder' => [qw( recur_included_hours recur_hourly_charge recur_hourly_cap recur_included_input recur_input_charge recur_input_cap recur_included_output recur_output_charge recur_output_cap recur_included_total recur_total_charge recur_total_cap global_cap )],
80   'weight' => 40,
81 );
82
83 sub price_info {
84     my $self = shift;
85     my $str = $self->SUPER::price_info(@_);
86     $str .= " plus usage" if $str;
87     $str;
88 }
89
90 sub calc_recur {
91   my($self, $cust_pkg, $sdate, $details ) = @_;
92
93   my $last_bill = $cust_pkg->last_bill;
94   my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $$sdate ) / 3600;
95   $hours -= $self->option('recur_included_hours');
96   $hours = 0 if $hours < 0;
97
98   my $input = $cust_pkg->attribute_since_sqlradacct(  $last_bill,
99                                                       $$sdate,
100                                                       'AcctInputOctets' )
101               / BU;
102
103   my $output = $cust_pkg->attribute_since_sqlradacct( $last_bill,
104                                                       $$sdate,
105                                                       'AcctOutputOctets' )
106                / BU;
107
108   my $total = $input + $output - $self->option('recur_included_total');
109   $total = 0 if $total < 0;
110   $input = $input - $self->option('recur_included_input');
111   $input = 0 if $input < 0;
112   $output = $output - $self->option('recur_included_output');
113   $output = 0 if $output < 0;
114
115   my $totalcharge =
116      sprintf('%.2f', $total * $self->option('recur_total_charge'));
117   $totalcharge = $self->option('recur_total_cap')
118     if $self->option('recur_total_cap')
119     && $totalcharge > $self->option('recur_total_cap');
120
121   my $inputcharge =
122      sprintf('%.2f', $input * $self->option('recur_input_charge'));
123   $inputcharge = $self->option('recur_input_cap')
124     if $self->option('recur_input_cap')
125     && $inputcharge > $self->option('recur_input_cap');
126
127   my $outputcharge = 
128     sprintf('%.2f', $output * $self->option('recur_output_charge'));
129   $outputcharge = $self->option('recur_output_cap')
130     if $self->option('recur_output_cap')
131     && $outputcharge > $self->option('recur_output_cap');
132
133   my $hourscharge =
134     sprintf('%.2f', $hours * $self->option('recur_hourly_charge'));
135   $hourscharge = $self->option('recur_hourly_cap')
136     if $self->option('recur_hourly_cap')
137     && $hourscharge > $self->option('recur_hourly_cap');
138
139   if ( $self->option('recur_total_charge') > 0 ) {
140     push @$details,
141       sprintf( "Last month's data %.3f %ss: %s", $total, BA, $totalcharge );
142   }
143   if ( $self->option('recur_input_charge') > 0 ) {
144     push @$details,
145       sprintf( "Last month's download %.3f %ss: %s", $input, BA, $inputcharge );
146   }
147   if ( $self->option('recur_output_charge') > 0 ) {
148     push @$details,
149       sprintf( "Last month's upload %.3f %ss: %s", $output, BA, $outputcharge );
150   }
151   if ( $self->option('recur_hourly_charge')  > 0 ) {
152     push @$details, "Last month\'s time ".
153                    sprintf('%.1f', $hours). " hours: $hourscharge";
154   }
155
156   my $charges = $hourscharge + $inputcharge + $outputcharge + $totalcharge;
157   if ( $self->option('global_cap') && $charges > $self->option('global_cap') ) {
158     $charges = $self->option('global_cap');
159     push @$details, "Usage charges capped at: $charges";
160   }
161
162   $self->option('recur_fee') + $charges;
163 }
164
165 sub can_discount { 0; }
166
167 sub is_free_options {
168   qw( setup_fee recur_fee recur_hourly_charge
169       recur_input_charge recur_output_charge recur_total_charge );
170 }
171
172 sub base_recur {
173   my($self, $cust_pkg) = @_;
174   $self->option('recur_fee');
175 }
176
177 1;