update flat_introrate plan to better fit current codebase RT#4912
[freeside.git] / FS / FS / ClientAPI / MyAccount.pm
index 213f6b4..298fe17 100644 (file)
@@ -10,7 +10,7 @@ use Business::CreditCard;
 use Time::Duration;
 use FS::UI::Web::small_custview qw(small_custview); #less doh
 use FS::UI::Web;
-use FS::UI::bytecount;
+use FS::UI::bytecount qw( display_bytecount );
 use FS::Conf;
 use FS::Record qw(qsearch qsearchs);
 use FS::Msgcat qw(gettext);
@@ -353,6 +353,9 @@ sub payment_info {
       'paytypes' => [ @FS::cust_main::paytypes ],
 
       'paybys' => [ $conf->config('signup_server-payby') ],
+      'cust_paybys' => [ map { FS::payby->payby2payment($_) }
+                                 $conf->config('signup_server-payby')
+                       ],
 
       'stateid_label' => FS::Msgcat::_gettext('stateid'),
       'stateid_state_label' => FS::Msgcat::_gettext('stateid_state'),
@@ -375,6 +378,18 @@ sub payment_info {
   my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
     or return { 'error' => "unknown custnum $custnum" };
 
+  $return{hide_payment_fields} =
+  [
+    map { FS::payby->realtime($_) &&
+          $cust_main
+            ->agent
+            ->payment_gateway( 'method' => FS::payby->payby2bop($_) )
+            ->gateway_namespace
+            eq 'Business::OnlineThirdPartyPayment'
+        }
+    @{ $return{cust_paybys} }
+  ];
+
   $return{balance} = $cust_main->balance;
 
   $return{payname} = $cust_main->payname
@@ -436,6 +451,7 @@ sub process_payment {
     or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} };
   my $paybatch = $1;
 
+  $p->{'payby'} ||= 'CARD';
   $p->{'payby'} =~ /^([A-Z]{4})$/
     or return { 'error' => "illegal_payby " . $p->{'payby'} };
   my $payby = $1;
@@ -490,7 +506,8 @@ sub process_payment {
   }
 
   my %payby2fields = (
-    'CARD' => [ qw( paystart_month paystart_year payissue address1 address2 city state zip payip ) ],
+    'CARD' => [ qw( paystart_month paystart_year payissue payip
+                    address1 address2 city state zip country    ) ],
     'CHEK' => [ qw( ss paytype paystate stateid stateid_state payip ) ],
   );
 
@@ -499,7 +516,7 @@ sub process_payment {
     'payinfo'  => $payinfo,
     'paydate'  => $p->{'year'}. '-'. $p->{'month'}. '-01',
     'payname'  => $payname,
-    'paybatch' => $paybatch,
+    'paybatch' => $paybatch, #this doesn't actually do anything
     'paycvv'   => $paycvv,
     map { $_ => $p->{$_} } @{ $payby2fields{$payby} }
   );
@@ -511,8 +528,8 @@ sub process_payment {
     my $new = new FS::cust_main { $cust_main->hash };
     if ($payby eq 'CARD' || $payby eq 'DCRD') {
       $new->set( $_ => $p->{$_} )
-        foreach qw( payname paystart_month paystart_year payissue payip
-                    address1 address2 city state zip payinfo );
+        foreach qw( payinfo payname paystart_month paystart_year payissue payip
+                    address1 address2 city state zip country );
       $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' );
     } elsif ($payby eq 'CHEK' || $payby eq 'DCHK') {
       $new->set( $_ => $p->{$_} )
@@ -531,6 +548,26 @@ sub process_payment {
 
 }
 
+sub realtime_collect {
+
+  my $p = shift;
+
+  my $session = _cache->get($p->{'session_id'})
+    or return { 'error' => "Can't resume session" }; #better error message
+
+  my $custnum = $session->{'custnum'};
+
+  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+    or return { 'error' => "unknown custnum $custnum" };
+
+  my $error = $cust_main->realtime_collect( 'method'     => $p->{'method'},
+                                            'session_id' => $p->{'session_id'},
+                                          );
+  return { 'error' => $error } unless ref( $error );
+
+  return { 'error' => '', amount => $cust_main->balance, %$error };
+}
+
 sub process_payment_order_pkg {
   my $p = shift;
 
@@ -736,8 +773,14 @@ sub list_svcs {
                          : $cust_main->unsuspended_pkgs ) {
     push @cust_svc, @{[ $cust_pkg->cust_svc ]}; #@{[ ]} to force array context
   }
-  @cust_svc = grep { $_->part_svc->svcdb eq $p->{'svcdb'} } @cust_svc
-    if $p->{'svcdb'};
+  if ( $p->{'svcdb'} ) {
+    my $svcdb = ref($p->{'svcdb'}) eq 'HASH'
+                  ? $p->{'svcdb'}
+                  : ref($p->{'svcdb'}) eq 'ARRAY'
+                    ? { map { $_=>1 } @{ $p->{'svcdb'} } }
+                    : { $p->{'svcdb'} => 1 };
+    @cust_svc = grep $svcdb->{ $_->part_svc->svcdb }, @cust_svc
+  }
 
   #@svc_x = sort { $a->domain cmp $b->domain || $a->username cmp $b->username }
   #              @svc_x;
@@ -745,30 +788,51 @@ sub list_svcs {
   { 
     #no#'svcnum'   => $session->{'svcnum'},
     'custnum'  => $custnum,
-    'svcs'     => [ map { 
-                          my $svc_x = $_->svc_x;
-                          my($label, $value) = $_->label;
-                          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'   => FS::UI::bytecount::display_bytecount($svc_x->upbytes),
-                            'downbytes' => FS::UI::bytecount::display_bytecount($svc_x->downbytes),
-                            'totalbytes'=> FS::UI::bytecount::display_bytecount($svc_x->totalbytes),
-                            'recharge_amount' => $part_pkg->option('recharge_amount', 1),
-                            'recharge_seconds' => $part_pkg->option('recharge_seconds', 1),
-                            'recharge_upbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_upbytes', 1)),
-                            'recharge_downbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_downbytes', 1)),
-                            'recharge_totalbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_totalbytes', 1)),
-                            # more...
-                          };
-                        }
-                        @cust_svc
-                  ],
+    'svcs'     => [
+      map { 
+            my $svc_x = $_->svc_x;
+            my($label, $value) = $_->label;
+            my $svcdb = $_->part_svc->svcdb;
+            my $part_pkg = $_->cust_pkg->part_pkg;
+
+            my %hash = (
+              'svcnum' => $_->svcnum,
+              'svcdb'  => $svcdb,
+              'label'  => $label,
+              'value'  => $value,
+            );
+
+            if ( $svcdb eq 'svc_acct' ) {
+              %hash = (
+                %hash,
+                'username'   => $svc_x->username,
+                'email'      => $svc_x->email,
+                'seconds'    => $svc_x->seconds,
+                'upbytes'    => display_bytecount($svc_x->upbytes),
+                'downbytes'  => display_bytecount($svc_x->downbytes),
+                'totalbytes' => display_bytecount($svc_x->totalbytes),
+
+                'recharge_amount'  => $part_pkg->option('recharge_amount',1),
+                'recharge_seconds' => $part_pkg->option('recharge_seconds',1),
+                'recharge_upbytes'    =>
+                  display_bytecount($part_pkg->option('recharge_upbytes',1)),
+                'recharge_downbytes'  =>
+                  display_bytecount($part_pkg->option('recharge_downbytes',1)),
+                'recharge_totalbytes' =>
+                  display_bytecount($part_pkg->option('recharge_totalbytes',1)),
+                # more...
+              );
+
+            } elsif ( $svcdb eq 'svc_phone' ) {
+              %hash = (
+                %hash,
+              );
+            }
+
+            \%hash;
+          }
+          @cust_svc
+    ],
   };
 
 }
@@ -778,9 +842,8 @@ sub _list_svc_usage {
   my @usage = ();
   foreach my $part_export ( 
     map { qsearch ( 'part_export', { 'exporttype' => $_ } ) }
-    qw (sqlradius sqlradius_withdomain')
+    qw( sqlradius sqlradius_withdomain )
   ) {
-
     push @usage, @ { $part_export->usage_sessions($begin, $end, $svc_acct) };
   }
   (@usage);
@@ -813,29 +876,50 @@ sub list_support_usage {
   _usage_details(\&_list_support_usage, @_);
 }
 
+sub _list_cdr_usage {
+  my($svc_phone, $begin, $end) = @_;
+  map [ $_->downstream_csv('format' => 'default') ], #XXX config for format
+      $svc_phone->cust_svc->get_cdrs( 'begin'=>$begin, 'end'=>$end, );
+}
+
+sub list_cdr_usage {
+  my $p = shift;
+  _usage_details( \&_list_cdr_usage, $p,
+                  'svcdb' => 'svc_phone',
+                );
+}
+
 sub _usage_details {
-  my ($callback, $p) = (shift,shift);
+  my($callback, $p, %opt) = @_;
 
   my($context, $session, $custnum) = _custoragent_session_custnum($p);
   return { 'error' => $session } if $context eq 'error';
 
   my $search = { 'svcnum' => $p->{'svcnum'} };
   $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
-  my $svc_acct = qsearchs ( 'svc_acct', $search );
+
+  my $svcdb = $opt{'svcdb'} || 'svc_acct';
+
+  my $svc_x = qsearchs( $svcdb, $search );
   return { 'error' => 'No service selected in list_svc_usage' } 
-    unless $svc_acct;
+    unless $svc_x;
 
-  my $freq   = $svc_acct->cust_svc->cust_pkg->part_pkg->freq;
-  my $start  = $svc_acct->cust_svc->cust_pkg->setup;
-  #my $end    = $svc_acct->cust_svc->cust_pkg->bill; # or time?
-  my $end    = time;
+  my $header = $svcdb eq 'svc_phone'
+                 ? [ split(',', FS::cdr::invoice_header('default') ) ]  #XXX
+                 : [];
 
-  unless($p->{beginning}){
-    $p->{beginning} = $svc_acct->cust_svc->cust_pkg->last_bill;
-    $p->{ending} = $end;
+  my $cust_pkg = $svc_x->cust_svc->cust_pkg;
+  my $freq     = $cust_pkg->part_pkg->freq;
+  my $start    = $cust_pkg->setup;
+  #my $end      = $cust_pkg->bill; # or time?
+  my $end      = time;
+
+  unless ( $p->{beginning} ) {
+    $p->{beginning} = $cust_pkg->last_bill;
+    $p->{ending}    = $end;
   }
 
-  my (@usage) = &$callback($svc_acct,$p->{beginning},$p->{ending});
+  my (@usage) = &$callback($svc_x, $p->{beginning}, $p->{ending});
 
   #kinda false laziness with FS::cust_main::bill, but perhaps
   #we should really change this bit to DateTime and DateTime::Duration
@@ -878,6 +962,7 @@ sub _usage_details {
     'ending'    => $p->{ending},
     'previous'  => ($previous > $start) ? $previous : $start,
     'next'      => ($next < $end) ? $next : $end,
+    'header'    => $header,
     'usage'     => \@usage,
   };
 }
@@ -921,6 +1006,7 @@ sub order_pkg {
     my %fields = (
       'svc_acct'     => [ qw( username domsvc _password sec_phrase popnum ) ],
       'svc_domain'   => [ qw( domain ) ],
+      'svc_phone'    => [ qw( phonenum pin sip_password ) ],
       'svc_external' => [ qw( id title ) ],
     );
   
@@ -1120,17 +1206,21 @@ sub renew_info {
 
   #return { 'error' => 'No active packages to renew.' } unless @cust_pkg;
 
-  my $total = 0;
+  my $total = $cust_main->balance;
 
   my @array = map {
-                    $total += $_->part_pkg->base_recur;
+                    my $bill = $_->bill;
+                    $total += $_->part_pkg->base_recur($_, \$bill);
                     my $renew_date = $_->part_pkg->add_freq($_->bill);
                     {
-                      'bill_date'         => $_->bill,
-                      'bill_date_pretty'  => time2str('%x', $_->bill),
-                      'renew_date'        => $renew_date,
-                      'renew_date_pretty' => time2str('%x', $renew_date),
-                      'amount'            => sprintf('%.2f', $total),
+                      'pkgnum'             => $_->pkgnum,
+                      'amount'             => sprintf('%.2f', $total),
+                      'bill_date'          => $_->bill,
+                      'bill_date_pretty'   => time2str('%x', $_->bill),
+                      'renew_date'         => $renew_date,
+                      'renew_date_pretty'  => time2str('%x', $renew_date),
+                      'expire_date'        => $_->expire,
+                      'expire_date_pretty' => time2str('%x', $_->expire),
                     };
                   }
                   @cust_pkg;
@@ -1139,6 +1229,15 @@ sub renew_info {
 
 }
 
+sub payment_info_renew_info {
+  my $p = shift;
+  my $renew_info   = renew_info($p);
+  my $payment_info = payment_info($p);
+  return { %$renew_info,
+           %$payment_info,
+         };
+}
+
 sub order_renew {
   my $p = shift;