retouch bandwidth countdown
authorjeff <jeff>
Thu, 7 Dec 2006 02:40:32 +0000 (02:40 +0000)
committerjeff <jeff>
Thu, 7 Dec 2006 02:40:32 +0000 (02:40 +0000)
20 files changed:
FS/FS/AccessRight.pm
FS/FS/ClientAPI/MyAccount.pm
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/cust_main.pm
FS/FS/cust_pkg.pm
FS/FS/part_pkg/flat.pm
FS/FS/part_pkg/prorate.pm
FS/FS/part_pkg/subscription.pm
FS/FS/prepay_credit.pm
FS/FS/svc_acct.pm
FS/FS/svc_broadband.pm
fs_selfservice/FS-SelfService/SelfService.pm
fs_selfservice/FS-SelfService/cgi/process_order_recharge.html [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/selfservice.cgi
fs_selfservice/FS-SelfService/cgi/view_usage.html
httemplate/edit/prepay_credit.cgi
httemplate/edit/process/prepay_credit.cgi
httemplate/misc/process/recharge_svc.html
httemplate/search/prepay_credit.html

index 8ba78d5..4a6da08 100644 (file)
@@ -114,6 +114,7 @@ assigned to users and/or groups.
 ###
 # customer service rights
 ###
+  'Edit usage',
   'Provision customer service',
   'Recharge customer service',
   'Unprovision customer service',
index eb49a6d..ff5b775 100644 (file)
@@ -22,6 +22,7 @@ use FS::cust_main;
 use FS::cust_bill;
 use FS::cust_main_county;
 use FS::cust_pkg;
+use HTML::Entities;
 
 use vars qw( @cust_main_editable_fields );
 @cust_main_editable_fields = qw(
@@ -379,24 +380,27 @@ sub process_prepay {
   my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
     or return { 'error' => "unknown custnum $custnum" };
 
-  my( $amount, $seconds, $upbytes, $downbytes ) = ( 0, 0, 0, 0 );
+  my( $amount, $seconds, $upbytes, $downbytes, $totalbytes ) = ( 0, 0, 0, 0, 0 );
   my $error = $cust_main->recharge_prepay( $p->{'prepaid_cardnum'},
                                            \$amount,
                                            \$seconds,
                                            \$upbytes,
-                                           \$downbytes
+                                           \$downbytes,
+                                           \$totalbytes,
                                          );
 
   return { 'error' => $error } if $error;
 
-  return { 'error'    => '',
-           'amount'   => $amount,
-           'seconds'  => $seconds,
-           'duration' => duration_exact($seconds),
-           'upbytes'  => $upbytes,
-           'upload'   => FS::UI::Web::bytecount_unexact($upbytes),
-           'downbytes'=> $downbytes,
-           'download' => FS::UI::Web::bytecount_unexact($downbytes),
+  return { 'error'     => '',
+           'amount'    => $amount,
+           'seconds'   => $seconds,
+           'duration'  => duration_exact($seconds),
+           'upbytes'   => $upbytes,
+           'upload'    => FS::UI::Web::bytecount_unexact($upbytes),
+           'downbytes' => $downbytes,
+           'download'  => FS::UI::Web::bytecount_unexact($downbytes),
+           'totalbytes'=> $totalbytes,
+           'totalload' => FS::UI::Web::bytecount_unexact($totalbytes),
          };
 
 }
@@ -563,15 +567,22 @@ sub list_svcs {
     'svcs'     => [ map { 
                           my $svc_x = $_->svc_x;
                           my($label, $value) = $_->label;
-
-                          { 'svcnum'   => $_->svcnum,
-                            'label'    => $label,
-                            'value'    => $value,
-                            'username' => $svc_x->username,
-                            'email'    => $svc_x->email,
-                            'seconds'  => $svc_x->seconds,
-                            'upbytes'  => $svc_x->upbytes,
-                            'downbytes'=> $svc_x->downbytes,
+                          my $part_pkg = $svc_x->cust_svc->cust_pkg->part_pkg;
+
+                          { 'svcnum'    => $_->svcnum,
+                            'label'     => $label,
+                            'value'     => $value,
+                            'username'  => $svc_x->username,
+                            'email'     => $svc_x->email,
+                            'seconds'   => $svc_x->seconds,
+                            'upbytes'   => $svc_x->upbytes,
+                            'downbytes' => $svc_x->downbytes,
+                            'totalbytes'=> $svc_x->totalbytes,
+                            'recharge_amount' => $part_pkg->option('recharge_amount'),
+                            'recharge_seconds' => $part_pkg->option('recharge_seconds'),
+                            'recharge_upbytes' => $part_pkg->option('recharge_upbytes'),
+                            'recharge_downbytes' => $part_pkg->option('recharge_downbytes'),
+                            'recharge_totalbytes' => $part_pkg->option('recharge_totalbytes'),
                             # more...
                           };
                         }
@@ -692,6 +703,73 @@ sub order_pkg {
 
 }
 
+sub order_recharge {
+  my $p = shift;
+
+  my($context, $session, $custnum) = _custoragent_session_custnum($p);
+  return { 'error' => $session } if $context eq 'error';
+
+  my $search = { 'custnum' => $custnum };
+  $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
+  my $cust_main = qsearchs('cust_main', $search )
+    or return { 'error' => "unknown custnum $custnum" };
+
+  my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $p->{'svcnum'} } )
+    or return { 'error' => "unknown service " . $p->{'svcnum'} };
+
+  my $svc_x = $cust_svc->svc_x;
+  my $part_pkg = $cust_svc->cust_pkg->part_pkg;
+
+  my %vhash =
+    map { $_ =~ /^recharge_(.*)$/; $1, $part_pkg->option($_) } 
+    qw ( recharge_seconds recharge_upbytes recharge_downbytes
+         recharge_totalbytes );
+  my $amount = $part_pkg->option('recharge_amount'); 
+  
+  my $old_balance = $cust_main->balance;
+
+  my ($l, $v, $d) = $cust_svc->label;  # blah
+  my $pkg = "Recharge $v"; 
+
+  my $bill_error = $cust_main->charge($amount, $pkg,
+     "time: $vhash{seconds}, up: $vhash{upbytes}," . 
+     "down: $vhash{downbytes}, total: $vhash{totalbytes}",
+     $part_pkg->taxclass); #meh
+
+  my $conf = new FS::Conf;
+  if ( $conf->exists('signup_server-realtime') && !$bill_error ) {
+
+    $bill_error = $cust_main->bill;
+
+    $cust_main->apply_payments;
+    $cust_main->apply_credits;
+    $bill_error = $cust_main->collect('realtime' => 1);
+
+    #false laziness with order_pkg
+    if (    $cust_main->balance > $old_balance
+         && $cust_main->balance > 0
+         && $cust_main->payby !~ /^(BILL|DCRD|DCHK)$/ ) {
+      #this makes sense.  credit is "un-doing" the invoice
+      $cust_main->credit( sprintf("%.2f", $cust_main->balance - $old_balance ),
+                          'self-service decline' );
+      $cust_main->apply_credits( 'order' => 'newest' );
+
+      return { 'error' => '_decline', 'bill_error' => encode_entities($bill_error) };
+    } else {
+      my $error = $svc_x->recharge (\%vhash);
+      return { 'error' => $error } if $error;
+    }
+
+  } else {  
+    my $error = $bill_error;
+    $error ||= $svc_x->recharge (\%vhash);
+    return { 'error' => $error } if $error;
+  }
+
+  return { error => '', svc => $cust_svc->part_svc->svc };
+
+}
+
 sub cancel_pkg {
   my $p = shift;
   my $session = _cache->get($p->{'session_id'})
index 5a07c1a..8f11fdb 100644 (file)
@@ -1456,6 +1456,33 @@ sub ut_phonen {
   '';
 }
 
+=item ut_hex COLUMN
+
+Check/untaint hexadecimal values.
+
+=cut
+
+sub ut_hex {
+  my($self, $field) = @_;
+  $self->getfield($field) =~ /^([\da-fA-F]+)$/
+    or return "Illegal (hex) $field: ". $self->getfield($field);
+  $self->setfield($field, uc($1));
+  '';
+}
+
+=item ut_hexn COLUMN
+
+Check/untaint hexadecimal values.  May be null.
+
+=cut
+
+sub ut_hexn {
+  my($self, $field) = @_;
+  $self->getfield($field) =~ /^([\da-fA-F]*)$/
+    or return "Illegal (hex) $field: ". $self->getfield($field);
+  $self->setfield($field, uc($1));
+  '';
+}
 =item ut_ip COLUMN
 
 Check/untaint ip addresses.  IPv4 only for now.
index 400ef06..a97c396 100644 (file)
@@ -932,6 +932,7 @@ sub tables_hashref {
         'seconds',     'int',     'NULL', '', '', '', 
         'upbytes',     'int',     'NULL', '', '', '', 
         'downbytes',   'int',     'NULL', '', '', '', 
+        'totalbytes',  'int',     'NULL', '', '', '', 
         'agentnum',    'int',     'NULL', '', '', '', 
       ],
       'primary_key' => 'prepaynum',
@@ -1144,6 +1145,10 @@ sub tables_hashref {
         'speed_up', 'int', '', '', '', '', 
         'speed_down', 'int', '', '', '', '', 
         'ip_addr', 'varchar', '', 15, '', '', 
+        'mac_addr', 'varchar', 'NULL', 12, '', '', 
+        'latitude', 'decimal', 'NULL', '', '', '', 
+        'longitude', 'decimal', 'NULL', '', '', '', 
+        'vlan', 'int', 'NULL', '', '', '', 
       ],
       'primary_key' => 'svcnum',
       'unique'      => [],
index e01154f..7127775 100644 (file)
@@ -708,7 +708,7 @@ card.
 
 sub recharge_prepay { 
   my( $self, $prepay_credit, $amountref, $secondsref, 
-      $upbytesref, $downbytesref ) = @_;
+      $upbytesref, $downbytesref, $totalbytesref ) = @_;
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -721,14 +721,14 @@ sub recharge_prepay {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  my( $amount, $seconds, $upbytes, $downbytes ) = ( 0, 0, 0, 0 );
+  my( $amount, $seconds, $upbytes, $downbytes, $totalbytes) = ( 0, 0, 0, 0, 0 );
 
   my $error = $self->get_prepay($prepay_credit, \$amount,
-                                \$seconds, \$upbytes, \$downbytes)
+                                \$seconds, \$upbytes, \$downbytes, \$totalbytes)
            || $self->increment_seconds($seconds)
            || $self->increment_upbytes($upbytes)
            || $self->increment_downbytes($downbytes)
-           || $self->increment_totalbytes($upbytes + $downbytes)
+           || $self->increment_totalbytes($totalbytes)
            || $self->insert_cust_pay_prepay( $amount,
                                              ref($prepay_credit)
                                                ? $prepay_credit->identifier
@@ -744,6 +744,7 @@ sub recharge_prepay {
   if ( defined($secondsref) ) { $$secondsref = $seconds; }
   if ( defined($upbytesref) ) { $$upbytesref = $upbytes; }
   if ( defined($downbytesref) ) { $$downbytesref = $downbytes; }
+  if ( defined($totalbytesref) ) { $$totalbytesref = $totalbytes; }
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';
@@ -767,7 +768,8 @@ If there is an error, returns the error, otherwise returns false.
 
 
 sub get_prepay {
-  my( $self, $prepay_credit, $amountref, $secondsref, $upref, $downref) = @_;
+  my( $self, $prepay_credit, $amountref, $secondsref,
+      $upref, $downref, $totalref) = @_;
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -816,6 +818,7 @@ sub get_prepay {
   $$secondsref += $prepay_credit->seconds;
   $$upref      += $prepay_credit->upbytes;
   $$downref    += $prepay_credit->downbytes;
+  $$totalref   += $prepay_credit->totalbytes;
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';
index ec47538..6807baf 100644 (file)
@@ -1452,6 +1452,26 @@ sub insert_reason {
   return $cust_pkg_reason->insert;
 }
 
+=item set_usage USAGE_VALUE_HASHREF 
+
+USAGE_VALUE_HASHREF is a hashref of svc_acct usage columns and the amounts
+to which they should be set (see L<FS::svc_acct>).  Currently seconds,
+upbytes, downbytes, and totalbytes are appropriate keys.
+
+All svc_accts which are part of this package have their values reset.
+
+=cut
+
+sub set_usage {
+  my ($self, $valueref) = @_;
+
+  foreach my $cust_svc ($self->cust_svc){
+    my $svc_x = $cust_svc->svc_x;
+    $svc_x->set_usage($valueref)
+      if $svc_x->can("set_usage");
+  }
+}
+
 =back
 
 =head1 BUGS
index bed86cc..39be379 100644 (file)
@@ -23,8 +23,39 @@ use FS::part_pkg;
     'externalid' => { 'name'   => 'Optional External ID',
                       'default' => '',
                     },
+    'seconds'       => { 'name' => 'Time limit for this package',
+                         'default' => '',
+                       },
+    'upbytes'       => { 'name' => 'Upload limit for this package',
+                         'default' => '',
+                       },
+    'downbytes'     => { 'name' => 'Download limit for this package',
+                         'default' => '',
+                       },
+    'totalbytes'    => { 'name' => 'Transfer limit for this package',
+                         'default' => '',
+                       },
+    'recharge_amount'       => { 'name' => 'Cost of recharge for this package',
+                         'default' => '',
+                       },
+    'recharge_seconds'      => { 'name' => 'Recharge time for this package',
+                         'default' => '',
+                       },
+    'recharge_upbytes'      => { 'name' => 'Recharge upload for this package',
+                         'default' => '',
+                       },
+    'recharge_downbytes'    => { 'name' => 'Recharge download for this package',
+                         'default' => '',
+                       },
+    'recharge_totalbytes'   => { 'name' => 'Recharge transfer for this package',
+                         'default' => '',
+                       },
   },
-  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'externalid' ],
+  'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 
+                    'seconds', 'upbytes', 'downbytes', 'totalbytes',
+                    'recharge_amount', 'recharge_seconds', 'recharge_upbytes',
+                    'recharge_downbytes', 'recharge_totalbytes',
+                    'externalid' ],
   'weight' => 10,
 );
 
@@ -34,8 +65,9 @@ sub calc_setup {
 }
 
 sub calc_recur {
-  my $self = shift;
-  $self->base_recur(@_);
+  my($self, $cust_pkg) = @_;
+  $self->reset_usage($cust_pkg);
+  $self->base_recur($cust_pkg);
 }
 
 sub base_recur {
@@ -78,4 +110,12 @@ sub is_prepaid {
   0; #no, we're postpaid
 }
 
+sub reset_usage {
+  my($self, $cust_pkg) = @_;
+  my %values = map { $_, $self->option($_) } 
+    grep { $self->option($_) } 
+    qw(seconds upbytes downbytes totalbytes);
+  $cust_pkg->set_usage(\%values);
+}
+
 1;
index e436679..7ce7364 100644 (file)
@@ -24,12 +24,40 @@ use FS::part_pkg::flat;
     'cutoff_day' => { 'name' => 'billing day',
                         'default' => 1,
                                            },
+    'seconds'       => { 'name' => 'Time limit for this package',
+                         'default' => '',
+                       },
+    'upbytes'       => { 'name' => 'Upload limit for this package',
+                         'default' => '',
+                       },
+    'downbytes'     => { 'name' => 'Download limit for this package',
+                         'default' => '',
+                       },
+    'totalbytes'    => { 'name' => 'Transfer limit for this package',
+                         'default' => '',
+                       },
+    'recharge_amount'       => { 'name' => 'Cost of recharge for this package',
+                         'default' => '',
+                       },
+    'recharge_seconds'      => { 'name' => 'Recharge time for this package',
+                         'default' => '',
+                       },
+    'recharge_upbytes'      => { 'name' => 'Recharge upload for this package',
+                         'default' => '',
+                       },
+    'recharge_downbytes'    => { 'name' => 'Recharge download for this package',                         'default' => '',
+                       },
+    'recharge_totalbytes'   => { 'name' => 'Recharge transfer for this package',                         'default' => '',
+                       },
     #it would be better if this had to be turned on, its confusing
     'externalid' => { 'name'   => 'Optional External ID',
                       'default' => '',
                     },
  },
   'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'cutoff_day',
+                    'seconds', 'upbyte', 'downbytes', 'totalbytes',
+                    'recharge_amount', 'recharge_seconds', 'recharge_upbytes',
+                    'recharge_downbytes', 'recharge_totalbytes',
                     'externalid', ],
   'freq' => 'm',
   'weight' => 20,
@@ -43,6 +71,8 @@ sub calc_recur {
   my $mend;
   my $mstart;
   
+  $self->reset_usage($cust_pkg);
+
   if ( $mday >= $cutoff_day ) {
     $mend =
       timelocal(0,0,0,$cutoff_day, $mon == 11 ? 0 : $mon+1, $year+($mon==11));
index 6b5da5c..db04842 100644 (file)
@@ -20,13 +20,46 @@ use FS::part_pkg::flat;
     'cutoff_day' => { 'name' => 'billing day',
                       'default' => 1,
                     },
+    'seconds'       => { 'name' => 'Time limit for this package',
+                         'default' => '',
+                       },
+    'upbytes'       => { 'name' => 'Upload limit for this package',
+                         'default' => '',
+                       },
+    'downbytes'     => { 'name' => 'Download limit for this package',
+                         'default' => '',
+                       },
+    'totalbytes'    => { 'name' => 'Transfer limit for this package',
+                         'default' => '',
+                       },
+    'recharge_amount'       => { 'name' => 'Cost of recharge for this package',
+                         'default' => '',
+                       },
+    'recharge_seconds'      => { 'name' => 'Recharge time for this package',
+                         'default' => '',
+                       },
+    'recharge_upbytes'      => { 'name' => 'Recharge upload for this package',
+                         'default' => '',
+                       },
+    'recharge_downbytes'    => { 'name' => 'Recharge download for this package',                         'default' => '',
+                       },
+    'recharge_totalbytes'   => { 'name' => 'Recharge transfer for this package',                         'default' => '',
+                       },
     #it would be better if this had to be turned on, its confusing
     'externalid' => { 'name'   => 'Optional External ID',
                       'default' => '',
                     },
   },
-  'fieldorder' => [ 'setup_fee', 'recur_fee', 'cutoff_day', 'externalid' ],
-  'fieldorder' => [ 'setup_fee', 'recur_fee','cutoff_day'],
+  'fieldorder' => [ 'setup_fee', 'recur_fee', 'cutoff_day', 'seconds',
+                    'upbytes', 'downbytes', 'totalbytes',
+                    'recharge_amount', 'recharge_seconds', 'recharge_upbytes',
+                    'recharge_downbytes', 'recharge_totalbytes',
+                    'externalid' ],
+  'fieldorder' => [ 'setup_fee', 'recur_fee','cutoff_day', 'seconds',
+                    'upbytes', 'downbytes', 'totalbytes',
+                    'recharge_amount', 'recharge_seconds', 'recharge_upbytes',
+                    'recharge_downbytes', 'recharge_totalbytes',
+                   ],
   'freq' => 'm',
   'weight' => 30,
 );
@@ -44,6 +77,8 @@ sub calc_recur {
 
   $$sdate = timelocal(0,0,0,$cutoff_day,$mon,$year);
 
+  $self->reset_usage($cust_pkg);
+
   $self->option('recur_fee');
 }
 
index 38e87ad..bf85dfa 100644 (file)
@@ -110,6 +110,9 @@ sub check {
   || $self->ut_alpha('identifier')
   || $self->ut_money('amount')
   || $self->ut_numbern('seconds')
+  || $self->ut_numbern('upbytes')
+  || $self->ut_numbern('downbytes')
+  || $self->ut_numbern('totalbytes')
   || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
   || $self->SUPER::check
   ;
index 3db12f6..6ba2f97 100644 (file)
@@ -1431,10 +1431,90 @@ sub _op_usage {
 
 }
 
+sub set_usage {
+  my( $self, $valueref ) = @_;
+
+  warn "$me set_usage called for svcnum ". $self->svcnum.
+       ' ('. $self->email. "): ".
+       join(', ', map { "$_ => " . $valueref->{$_}} keys %$valueref) . "\n"
+    if $DEBUG;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  if ( $conf->exists("svc_acct-usage_unsuspend") ) {
+    my $error = $self->cust_svc->cust_pkg->unsuspend;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "Error unsuspending: $error";
+    }
+  }
+
+  foreach my $field (keys %$valueref){
+    $self->setfield($field, $valueref->{$field});
+    $self->setfield( $field.'_threshold',
+                     int($self->getfield($field)
+                         * ( $conf->exists('svc_acct-usage_threshold') 
+                             ? 1 - $conf->config('svc_acct-usage_threshold')/100
+                             : 0.20
+                           )
+                       )
+                     );
+  }
+  my $error = $self->replace;
+  die $error if $error;
+
+  warn "$me update successful; committing\n"
+    if $DEBUG;
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  '';
+
+}
+
+
+=item recharge HASHREF
+
+  Increments usage columns by the amount specified in HASHREF as
+  column=>amount pairs.
+
+=cut
+
+sub recharge {
+  my ($self, $vhash) = @_;
+   
+  if ( $DEBUG ) {
+    warn "[$me] recharge called on $self: ". Dumper($self).
+         "\nwith vhash: ". Dumper($vhash);
+  }
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+  my $error = '';
+
+  foreach my $column (keys %$vhash){
+    $error ||= $self->_op_usage('+', $column, $vhash->{$column});
+  }
+
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+  }else{
+    $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  }
+  return $error;
+}
 
 =item is_rechargeable
 
-Returns true if this svc_account can be "rechaged" and false otherwise.
+Returns true if this svc_account can be "recharged" and false otherwise.
 
 =cut
 
@@ -1956,7 +2036,7 @@ sub reached_threshold {
   }elsif ( $opt{'op'} eq '-' ){
     
     my $threshold = $svc_acct->getfield( $opt{'column'}.'_threshold' );
-    return '' if ($threshold eq '' && opt{'column'} eq 'totalbytes');
+    return '' if ($threshold eq '' );
 
     $svc_acct->setfield( $opt{'column'}.'_threshold', 0 );
     my $error = $svc_acct->replace;
index aaac891..f4cc794 100755 (executable)
@@ -154,12 +154,24 @@ sub check {
     || $self->ut_number('speed_up')
     || $self->ut_number('speed_down')
     || $self->ut_ipn('ip_addr')
+    || $self->ut_hexn('mac_addr')
+    || $self->ut_numbern('vlan')
   ;
   return $error if $error;
 
   if($self->speed_up < 0) { return 'speed_up must be positive'; }
   if($self->speed_down < 0) { return 'speed_down must be positive'; }
 
+  if($self->vlan < 0 || $self->vlan > 4096) { # apropos?
+    return 'vlan is out of range'; }
+
+  if($self->latitude < -90 || $self->latitude > 90) {
+    return 'latitude must be between -90 and 90';
+  }
+  if($self->longitude < -180 || $self->longitude > 180) {
+    return 'longitude must be between -180 and 180';
+  }
+
   if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') {
     my $next_addr = $self->addr_block->next_free_addr;
     if ($next_addr) {
index 216e372..980c899 100644 (file)
@@ -38,6 +38,7 @@ $socket .= '.'.$tag if defined $tag && length($tag);
   'list_pkgs'            => 'MyAccount/list_pkgs',     #add to ss cgi (added?)
   'list_svcs'            => 'MyAccount/list_svcs',     #add to ss cgi (added?)
   'order_pkg'            => 'MyAccount/order_pkg',     #add to ss cgi!
+  'order_recharge'       => 'MyAccount/order_recharge',
   'cancel_pkg'           => 'MyAccount/cancel_pkg',    #add to ss cgi!
   'charge'               => 'MyAccount/charge',        #?
   'part_svc_info'        => 'MyAccount/part_svc_info',
diff --git a/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html b/fs_selfservice/FS-SelfService/cgi/process_order_recharge.html
new file mode 100644 (file)
index 0000000..851bbed
--- /dev/null
@@ -0,0 +1,13 @@
+<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
+<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= include('myaccount_menu') %>
+<TD VALIGN="top">
+
+<FONT SIZE=4><%= $svc %> recharged successfully.</FONT>
+
+</TD></TR></TABLE>
+<HR>
+<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
+</BODY></HTML>
+
index 1a2c74a..e2fd7f6 100644 (file)
@@ -10,7 +10,7 @@ use HTML::Entities;
 use FS::SelfService qw( login customer_info invoice
                         payment_info process_payment 
                         process_prepay
-                        list_pkgs order_pkg signup_info
+                        list_pkgs order_pkg signup_info order_recharge
                         part_svc_info provision_acct provision_external
                         unprovision_svc
                         list_svcs myaccount_passwd
@@ -65,7 +65,7 @@ $session_id = $cgi->param('session');
 
 #order|pw_list XXX ???
 $cgi->param('action') =~
-    /^(myaccount|view_invoice|make_payment|payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|customer_order_pkg|process_order_pkg|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage||change_password|process_change_password)$/
+    /^(myaccount|view_invoice|make_payment|payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|customer_order_pkg|process_order_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage||change_password|process_change_password)$/
   or die "unknown action ". $cgi->param('action');
 my $action = $1;
 
@@ -160,6 +160,33 @@ sub process_order_pkg {
 
 }
 
+sub process_order_recharge {
+
+  my $results = '';
+
+  $results ||= order_recharge (
+    'session_id' => $session_id,
+    map { $_ => $cgi->param($_) }
+        qw( svcnum )
+  );
+
+
+  if ( $results->{'error'} ) {
+    $action = 'view_usage';
+    if ($results->{'error'} eq '_decline') {
+      $results->{'error'} = "There has been an error processing your account.  Please contact customer support."
+    }
+    return {
+      $cgi->Vars,
+      %{view_usage()},
+      'error' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
+    };
+  } else {
+    return $results;
+  }
+
+}
+
 sub make_payment {
   payment_info( 'session_id' => $session_id );
 }
index 40aec7b..73ad1e4 100644 (file)
@@ -6,8 +6,9 @@
 
 <FONT SIZE=4>Service usage</FONT><BR><BR>
 
-<FORM ACTION="<%= $selfurl %>" METHOD="POST">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
+<%= if ( $error ) {
+  $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
+} ''; %>
 
 <TABLE BGCOLOR="#cccccc">
   <TR>
     <TH ALIGN="right">Total remaining</TH>
   </TR>
 <%= foreach my $svc ( @svcs ) {
-    my $totalbytes = '';
-    if ( ($svc->{'upbytes'}   + 0) eq $svc->{'upbytes'}
-      || ($svc->{'downbytes'} + 0) eq $svc->{'downbytes'} ) {
-
-      $totalbytes = $svc->{'upbytes'} + $svc->{'downbytes'};
-    }
-
   $OUT .= '<TR><TD>';
     $OUT .= $svc->{'label'}. ': '. $svc->{'value'};
     $OUT .= '</TD><TD ALIGN="right">';
     $OUT .= '</TD><TD ALIGN="right">';
     $OUT .= $svc->{'downbytes'};
     $OUT .= '</TD><TD ALIGN="right">';
-    $OUT .= $totalbytes;
+    $OUT .= $svc->{'totalbytes'};
   $OUT .= '</TD></TR>';
+    if ( $svc->{'recharge_amount'} ) {
+      my $link = "${url}process_order_recharge;".
+                 "svcnum=$svc->{'svcnum'}";
+    $OUT .= '<TR><TD ALIGN="right">';
+      $OUT .= qq!<A HREF="$link">!.'Recharge for $';
+      $OUT .= $svc->{'recharge_amount'} . '</A> with';
+      $OUT .= '</TD><TD ALIGN="right">';
+      $OUT .= $svc->{'recharge_seconds'} if $svc->{'recharge_seconds'};
+      $OUT .= '</TD><TD ALIGN="right">';
+      $OUT .=  $svc->{'recharge_upbytes'} if $svc->{'recharge_upbytes'};
+      $OUT .= '</TD><TD ALIGN="right">';
+      $OUT .= $svc->{'recharge_downbytes'} if $svc->{'recharge_downbytes'};
+      $OUT .= '</TD><TD ALIGN="right">';
+      $OUT .= $svc->{'recharge_totalbytes'} if $svc->{'recharge_totalbytes'};
+    $OUT .= '</TD></TR>';
+    }
   } %>
 
 </TABLE>
 <BR>
 
-</FORM>
-
 </TD></TR></TABLE>
 <HR>
 <FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
index 7ce44c0..c22904d 100644 (file)
@@ -21,6 +21,7 @@
 %$cgi->param('multiplier',     '60')      unless $cgi->param('multiplier');
 %$cgi->param('upmultiplier',   '1000000') unless $cgi->param('upmultiplier');
 %$cgi->param('downmultiplier', '1000000') unless $cgi->param('downmultiplier');
+%$cgi->param('totalmultiplier','1000000') unless $cgi->param('totalmultiplier');
 %
 %
 
@@ -91,6 +92,17 @@ $<INPUT TYPE="text" NAME="amount" SIZE=8 MAXLENGTH=7 VALUE="<% $cgi->param('amou
 
 </SELECT> download
 </TD></TR>
+<TR><TD></TD>
+<TD>and/or
+<INPUT TYPE="text" NAME="totalbytes" SIZE=6 MAXLENGTH=5 VALUE="<% $cgi->param('totalbytes') %>">
+<SELECT NAME="totalmultiplier">
+% foreach my $multiplier ( keys %bytemultiplier ) { 
+
+  <OPTION VALUE="<% $multiplier %>"<% $cgi->param('totalmultiplier') eq $multiplier ? ' SELECTED' : '' %>><% $bytemultiplier{$multiplier} %>
+% } 
+
+</SELECT> total transfer
+</TD></TR>
 </TABLE>
 <BR><BR>
 <INPUT TYPE="submit" NAME="submit" VALUE="Generate" onSubmit="this.disabled = true">
index ba42969..6bf46bf 100644 (file)
@@ -19,6 +19,7 @@
 %$hashref->{seconds}   = $cgi->param('seconds') * $cgi->param('multiplier');
 %$hashref->{upbytes}   = $cgi->param('upbytes') * $cgi->param('upmultiplier');
 %$hashref->{downbytes} = $cgi->param('downbytes') * $cgi->param('downmultiplier');
+%$hashref->{totalbytes} = $cgi->param('totalbytes') * $cgi->param('totalmultiplier');
 %
 %$error ||= FS::prepay_credit::generate( $num,
 %                                        scalar($cgi->param('type')), 
@@ -50,6 +51,7 @@
   <% $hashref->{seconds} ? duration_exact($hashref->{seconds}) : '' %>
   <% $hashref->{upbytes}   ? FS::UI::Web::bytecount_unexact($hashref->{upbytes}) : '' %>
   <% $hashref->{downbytes} ? FS::UI::Web::bytecount_unexact($hashref->{downbytes}) : '' %>
+  <% $hashref->{totalbytes} ? FS::UI::Web::bytecount_unexact($hashref->{totalbytes}) : '' %>
   <br>
 % } 
 
index ae52668..d9fa207 100755 (executable)
 %
 %unless ($error) {
 %
-%my ($amount, $seconds, $up, $down) = (0, 0, 0, 0);
-%$error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down)
+%my ($amount, $seconds, $up, $down, $total) = (0, 0, 0, 0, 0);
+%$error = $cust_main->get_prepay($prepaid, \$amount, \$seconds, \$up, \$down, \$total)
 %      || $svc_acct->increment_seconds($seconds)
 %      || $svc_acct->increment_upbytes($up)
 %      || $svc_acct->increment_downbytes($down)
-%      || $svc_acct->increment_totalbytes($up + $down)
+%      || $svc_acct->increment_totalbytes($total)
 %      || $cust_main->insert_cust_pay_prepay( $amount, $prepaid );
 %}
 %
index fecb12f..c79acb0 100644 (file)
                                   },
                  'count_query' => $count_query,
                  #'redirect'    => $link,
-                 'header'      => [ '#', qw(Amount Time Upload Download Agent) ],
+                 'header'      => [ '#', qw(Amount Time Upload Download Total Agent) ],
                  'fields'      => [
                    'identifier',
                    sub { sprintf('$%.2f', shift->amount ) },
-                   sub { my $c = shift; $c ? duration_exact($c->seconds) : '' },
                    sub { my $c = shift;
-                         $c ? FS::UI::Web::bytecount_unexact($c->upbytes) : ''
+                         $c->seconds ? duration_exact($c->seconds) : ''
                        },
                    sub { my $c = shift;
-                         $c ? FS::UI::Web::bytecount_unexact($c->downbytes) : ''
+                         $c->upbytes 
+                           ? FS::UI::Web::bytecount_unexact($c->upbytes)
+                           : ''
+                       },
+                   sub { my $c = shift;
+                         $c->downbytes
+                           ? FS::UI::Web::bytecount_unexact($c->downbytes)
+                           : ''
+                       },
+                   sub { my $c = shift;
+                         $c->totalbytes
+                           ? FS::UI::Web::bytecount_unexact($c->totalbytes)
+                           : ''
                        },
                    sub { my $agent = shift->agent;
                          $agent ? $agent->agent : '';
@@ -43,6 +54,7 @@
                    '',
                    '',
                    '',
+                   '',
                    sub { my $agent = shift->agent;
                          $agent ? [ "${p}view/agent.cgi?", 'agentnum' ] : '';
                        },