summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Conf.pm14
-rw-r--r--FS/FS/UI/Web.pm26
-rw-r--r--FS/FS/part_pkg.pm33
-rw-r--r--FS/FS/part_pkg/flat.pm16
-rw-r--r--FS/FS/part_svc.pm8
-rw-r--r--FS/FS/svc_acct.pm47
-rw-r--r--FS/bin/freeside-queued1
-rwxr-xr-xhttemplate/browse/part_pkg.cgi2
-rwxr-xr-xhttemplate/browse/part_svc.cgi5
-rwxr-xr-xhttemplate/edit/part_pkg.cgi4
-rwxr-xr-xhttemplate/edit/part_svc.cgi7
-rwxr-xr-xhttemplate/edit/process/part_pkg.cgi8
-rwxr-xr-xhttemplate/edit/process/svc_acct.cgi5
-rwxr-xr-xhttemplate/edit/svc_acct.cgi28
-rwxr-xr-xhttemplate/view/svc_acct.cgi15
15 files changed, 186 insertions, 33 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 374b583..8bff460 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -1755,6 +1755,20 @@ httemplate/docs/config.html
'type' => 'checkbox',
},
+ {
+ 'key' => 'datavolume-forcemegabytes',
+ 'section' => 'UI',
+ 'description' => 'All data volumes are expressed in megabytes',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'datavolume-significantdigits',
+ 'section' => 'UI',
+ 'description' => 'number of significant digits to use to represent data volumes',
+ 'type' => 'text',
+ },
+
);
1;
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index 9ddcf14..a05a667 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -4,6 +4,7 @@ use strict;
use vars qw($DEBUG $me);
use FS::Conf;
use FS::Record qw(dbdef);
+use Number::Format;
#use vars qw(@ISA);
#use FS::UI
@@ -186,6 +187,31 @@ sub bytecount_unexact {
return(sprintf("%.2f Gbytes", $bc/1000000000));
}
+sub parse_bytecount {
+ my $bc = shift;
+ return $bc if (($bc =~ tr/.//) > 1);
+ $bc =~ /^\s*([\d.]*)\s*([kKmMgGtT]?)[bB]?\s*$/ or return $bc;
+ my $base = $1;
+ return $bc unless length $base;
+ my $exponent = index ' kmgt', lc($2);
+ return $bc if ($exponent < 0 && $2);
+ $exponent = 0 if ($exponent < 0);
+ return $base * 1024 ** $exponent;
+}
+
+sub display_bytecount {
+ my $bc = shift;
+ return $bc unless ($bc =~ /^(\d+)$/);
+ my $conf = new FS::Conf;
+ my $f = new Number::Format;
+ my $precision = $conf->exists('datavolume-significantdigits')
+ ? $conf->config('datavolume-significantdigits')
+ : 3;
+ my $unit = $conf->exists('datavolume-forcemegabytes') ? 'M' : 'A';
+
+ return $f->format_bytes($bc, precision => $precision, unit => $unit);
+}
+
###
# cust_main report subroutines
###
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index 03222fa..3110c1c 100644
--- a/FS/FS/part_pkg.pm
+++ b/FS/FS/part_pkg.pm
@@ -817,6 +817,39 @@ sub plan_info {
\%plans;
}
+=item format OPTION DATA
+
+Returns data formatted according to the function 'format' described
+in the plan info. Returns DATA if no such function exists.
+
+=cut
+
+sub format {
+ my ($self, $option, $data) = (shift, shift, shift);
+ if (exists($plans{$self->plan}->{fields}->{$option}{format})) {
+ &{$plans{$self->plan}->{fields}->{$option}{format}}($data);
+ }else{
+ $data;
+ }
+}
+
+=item prase OPTION DATA
+
+Returns data parsed according to the function 'parse' described
+in the plan info. Returns DATA if no such function exists.
+
+=cut
+
+sub parse {
+ my ($self, $option, $data) = (shift, shift, shift);
+ if (exists($plans{$self->plan}->{fields}->{$option}{parse})) {
+ &{$plans{$self->plan}->{fields}->{$option}{parse}}($data);
+ }else{
+ $data;
+ }
+}
+
+
=back
=head1 NEW PLAN CLASSES
diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm
index 94b7d99..c0fbb5a 100644
--- a/FS/FS/part_pkg/flat.pm
+++ b/FS/FS/part_pkg/flat.pm
@@ -28,27 +28,43 @@ use FS::part_pkg;
},
'upbytes' => { 'name' => 'Upload limit for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'downbytes' => { 'name' => 'Download limit for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'totalbytes' => { 'name' => 'Transfer limit for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'recharge_amount' => { 'name' => 'Cost of recharge for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'recharge_seconds' => { 'name' => 'Recharge time for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'recharge_upbytes' => { 'name' => 'Recharge upload for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'recharge_downbytes' => { 'name' => 'Recharge download for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
'recharge_totalbytes' => { 'name' => 'Recharge transfer for this package',
'default' => '',
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
},
},
'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit',
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 5b4e54c..4fae457 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -145,9 +145,11 @@ sub insert {
my $flag = $self->getfield($svcdb.'__'.$field.'_flag');
#if ( uc($flag) =~ /^([DFMAX])$/ ) {
if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it
+ my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+ || sub { shift };
$part_svc_column->setfield('columnflag', $1);
$part_svc_column->setfield('columnvalue',
- $self->getfield($svcdb.'__'.$field)
+ &$parser($self->getfield($svcdb.'__'.$field))
);
if ( $previous ) {
$error = $part_svc_column->replace($previous);
@@ -264,9 +266,11 @@ sub replace {
my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
#if ( uc($flag) =~ /^([DFMAX])$/ ) {
if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it
+ my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+ || sub { shift };
$part_svc_column->setfield('columnflag', $1);
$part_svc_column->setfield('columnvalue',
- $new->getfield($svcdb.'__'.$field)
+ &$parser($new->getfield($svcdb.'__'.$field))
);
if ( $previous ) {
$error = $part_svc_column->replace($previous);
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 1ef2119..be5a6d3 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -273,6 +273,53 @@ sub table_info {
disable_inventory => 1,
disable_select => 1,
},
+ 'upbytes' => { label => 'Upload',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
+ 'downbytes' => { label => 'Download',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
+ 'totalbytes'=> { label => 'Total up and download',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
+ 'seconds_threshold' => { label => 'Seconds',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ },
+ 'upbytes_threshold' => { label => 'Upload',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
+ 'downbytes_threshold' => { label => 'Download',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
+ 'totalbytes_threshold'=> { label => 'Total up and download',
+ type => 'text',
+ disable_inventory => 1,
+ disable_select => 1,
+ 'format' => \&FS::UI::Web::display_bytecount,
+ 'parse' => \&FS::UI::Web::parse_bytecount,
+ },
},
};
}
diff --git a/FS/bin/freeside-queued b/FS/bin/freeside-queued
index 93d735d..b3128f0 100644
--- a/FS/bin/freeside-queued
+++ b/FS/bin/freeside-queued
@@ -9,6 +9,7 @@ use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
use FS::Record qw(qsearch qsearchs);
use FS::queue;
use FS::queue_depend;
+use FS::UI::Web;
# no autoloading for non-FS classes...
use Net::SSH 0.07;
diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
index 6b62ec6..5acf17e 100755
--- a/httemplate/browse/part_pkg.cgi
+++ b/httemplate/browse/part_pkg.cgi
@@ -189,7 +189,7 @@ push @fields, sub { shift->plan || '(legacy)' },
{ 'data' => $1,
'align' => 'right',
},
- { 'data' => $2,
+ { 'data' => $part_pkg->format($1,$2),
'align' => 'left',
},
];
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
index 3694955..92c0840 100755
--- a/httemplate/browse/part_svc.cgi
+++ b/httemplate/browse/part_svc.cgi
@@ -135,6 +135,9 @@ function part_export_areyousure(href) {
%
% my($n1)='';
% foreach my $field ( @fields ) {
+% my $formatter =
+% FS::part_svc->svc_table_fields($svcdb)->{$field}->{format}
+% || sub { shift };
% my $flag = $part_svc->part_svc_column($field)->columnflag;
%
@@ -143,7 +146,7 @@ function part_export_areyousure(href) {
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $flag{$flag} %></TD>
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
-% my $value = $part_svc->part_svc_column($field)->columnvalue;
+% my $value = &$formatter($part_svc->part_svc_column($field)->columnvalue);
% if ( $flag =~ /^[MA]$/ ) {
% $inventory_class{$value}
% ||= qsearchs('inventory_class', { 'classnum' => $value } );
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index ce3e854..bdd3f30 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -323,10 +323,12 @@ Reseller information
%
% $html .= '<TR><TD ALIGN="right">'. $href->{$field}{'name'}. '</TD><TD>';
%
+% my $format = sub { shift };
+% $format = $href->{$field}{'format'} if exists($href->{$field}{'format'});
% if ( ! exists($href->{$field}{'type'}) ) {
% $html .= qq!<INPUT TYPE="text" NAME="$field" VALUE="!.
% ( exists($plandata{$field})
-% ? $plandata{$field}
+% ? &$format($plandata{$field})
% : $href->{$field}{'default'} ).
% qq!">!;
% } elsif ( $href->{$field}{'type'} eq 'checkbox' ) {
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index 6ba9240..9432839 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -166,12 +166,13 @@ that field.
%
% foreach my $field (@fields) {
%
-% my $part_svc_column = $part_svc->part_svc_column($field);
-% my $value = $part_svc_column->columnvalue;
-% my $flag = $part_svc_column->columnflag;
% #my $def = $defs{$layer}{$field};
% my $def = FS::part_svc->svc_table_fields($layer)->{$field};
% my $label = $def->{'def_label'} || $def->{'label'};
+% my $formatter = $def->{'format'} || sub { shift };
+% my $part_svc_column = $part_svc->part_svc_column($field);
+% my $value = &$formatter($part_svc_column->columnvalue);
+% my $flag = $part_svc_column->columnflag;
%
% if ( $bgcolor eq $bgcolor1 ) {
% $bgcolor = $bgcolor2;
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
index 1158222..5fc59c1 100755
--- a/httemplate/edit/process/part_pkg.cgi
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -6,11 +6,17 @@
%
%my $old = qsearchs('part_pkg',{'pkgpart'=>$pkgpart}) if $pkgpart;
%
+%tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() };
+%my $href = $plans{$cgi->param('plan')}->{'fields'};
+%
%#fixup plandata
%my $plandata = $cgi->param('plandata');
%my @plandata = split(',', $plandata);
%$cgi->param('plandata',
-% join('', map { "$_=". join(', ', $cgi->param($_)). "\n" } @plandata )
+% join('', map { my $parser = sub { shift };
+% $parser = $href->{$_}{parse} if exists($href->{$_}{parse});
+% "$_=". join(', ', &$parser($cgi->param($_))). "\n"
+% } @plandata )
%);
%
%foreach (qw( setuptax recurtax disabled )) {
diff --git a/httemplate/edit/process/svc_acct.cgi b/httemplate/edit/process/svc_acct.cgi
index 30552c8..65ac5c1 100755
--- a/httemplate/edit/process/svc_acct.cgi
+++ b/httemplate/edit/process/svc_acct.cgi
@@ -23,6 +23,11 @@
%#unmunge usergroup
%$cgi->param('usergroup', [ $cgi->param('radius_usergroup') ] );
%
+%#unmunge bytecounts
+%foreach (map { $_,$_."_threshold" } qw( upbytes downbytes totalbytes )) {
+% $cgi->param($_, FS::UI::Web::parse_bytecount($cgi->param($_)) );
+%}
+%
%my %hash = $svcnum ? $old->hash : ();
%map {
% $hash{$_} = scalar($cgi->param($_));
diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi
index 01f665a..e0610b2 100755
--- a/httemplate/edit/svc_acct.cgi
+++ b/httemplate/edit/svc_acct.cgi
@@ -386,27 +386,27 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
</TR>
% }
%
-% if ( $curuser->access_right('Edit usage') ) {
-% my %label = ( seconds => 'Seconds',
-% upbytes => 'Upload bytes',
-% downbytes => 'Download bytes',
-% totalbytes => 'Total bytes',
-% );
-% foreach my $uf (keys %label) {
-% my $tf = $uf . "_threshold";
-% if ( $svc_acct->$tf ne '' ) {
-
+% my %label = ( seconds => 'Time',
+% upbytes => 'Upload bytes',
+% downbytes => 'Download bytes',
+% totalbytes => 'Total bytes',
+% );
+% foreach my $uf (keys %label) {
+% my $tf = $uf . "_threshold";
+% if ( $curuser->access_right('Edit usage') ) {
<TR>
<TD ALIGN="right"><% $label{$uf} %> remaining</TD>
- <TD><INPUT TYPE="text" NAME="<% $uf %>" VALUE="<% $svc_acct->$uf %>"></TD>
+ <TD><INPUT TYPE="text" NAME="<% $uf %>" VALUE="<% $svc_acct->$uf %>">(blank disables)</TD>
</TR>
<TR>
<TD ALIGN="right"><% $label{$uf} %> threshold</TD>
- <TD><INPUT TYPE="text" NAME="<% $tf %>" VALUE="<% $svc_acct->$tf %>">(blank or zero disables <% lc($label{$uf}) %> remaining)</TD>
+ <TD><INPUT TYPE="text" NAME="<% $tf %>" VALUE="<% $svc_acct->$tf %>">(blank disables)</TD>
</TR>
-% }
+% }else{
+ <INPUT TYPE="hidden" NAME="<% $uf %>" VALUE="<% $svc_acct->$uf %>">
+ <INPUT TYPE="hidden" NAME="<% $tf %>" VALUE="<% $svc_acct->$tf %>">
% }
-% }
+% }
%
%foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) {
% $r =~ /^^r(adius|[cr])_(.+)$/ or next; #?
diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi
index 8647868..2ad9b8e 100755
--- a/httemplate/view/svc_acct.cgi
+++ b/httemplate/view/svc_acct.cgi
@@ -245,17 +245,19 @@ Service #<B><% $svcnum %></B>
</TD>
</TR>
% }
-% my %ulabel = ( seconds => 'Seconds',
+% my %ulabel = ( seconds => 'Time',
% upbytes => 'Upload bytes',
% downbytes => 'Download bytes',
% totalbytes => 'Total bytes',
% );
% foreach my $uf ( keys %ulabel ) {
% my $tf = $uf . "_threshold";
-% if ( $svc_acct->$tf ne '' ) {
+% if ( $svc_acct->$uf ne '' ) {
+% my $v = $uf eq 'seconds' ? duration_exact($svc_acct->$uf)
+% : FS::UI::Web::display_bytecount($svc_acct->$uf);
<TR>
<TD ALIGN="right"><% $ulabel{$uf} %> remaining</TD>
- <TD BGCOLOR="#ffffff"><% $svc_acct->$uf %></TD>
+ <TD BGCOLOR="#ffffff"><% $v %></TD>
</TR>
% }
@@ -286,13 +288,6 @@ Service #<B><% $svcnum %></B>
<TD ALIGN="right">RADIUS groups</TD>
<TD BGCOLOR="#ffffff"><% join('<BR>', $svc_acct->radius_groups) %></TD>
</TR>
-% if ( $svc_acct->seconds =~ /^\d+$/ ) {
-
- <TR>
- <TD ALIGN="right">Prepaid time</TD>
- <TD BGCOLOR="#ffffff"><% duration_exact($svc_acct->seconds) %></TD>
- </TR>
-% }
%
%# Can this be abstracted further? Maybe a library function like
%# widget('HTML', 'view', $svc_acct) ? It would definitely make UI