selfservice password reset, RT#13656
[freeside.git] / FS / FS / ClientAPI / MyAccount.pm
index 7608439..784a33f 100644 (file)
@@ -4,12 +4,16 @@ use 5.008; #require 5.8+ for Time::Local 1.05+
 use strict;
 use vars qw( $cache $DEBUG $me );
 use subs qw( _cache _provision );
+use IO::Scalar;
 use Data::Dumper;
 use Digest::MD5 qw(md5_hex);
 use Date::Format;
-use Business::CreditCard;
 use Time::Duration;
 use Time::Local qw(timelocal_nocheck);
+use Business::CreditCard;
+use HTML::Entities;
+use Text::CSV_XS;
+use Spreadsheet::WriteExcel;
 use FS::UI::Web::small_custview qw(small_custview); #less doh
 use FS::UI::Web;
 use FS::UI::bytecount qw( display_bytecount );
@@ -19,6 +23,7 @@ use FS::Record qw(qsearch qsearchs dbh);
 use FS::Msgcat qw(gettext);
 use FS::Misc qw(card_types);
 use FS::Misc::DateTime qw(parse_datetime);
+use FS::TicketSystem;
 use FS::ClientAPI_SessionCache;
 use FS::cust_svc;
 use FS::svc_acct;
@@ -30,15 +35,12 @@ use FS::dsl_device;
 use FS::part_svc;
 use FS::cust_main;
 use FS::cust_bill;
+use FS::legacy_cust_bill;
 use FS::cust_main_county;
 use FS::cust_pkg;
 use FS::payby;
 use FS::acct_rt_transaction;
-use HTML::Entities;
-use FS::TicketSystem;
-use Text::CSV_XS;
-use IO::Scalar;
-use Spreadsheet::WriteExcel;
+use FS::msg_template;
 
 $DEBUG = 0;
 $me = '[FS::ClientAPI::MyAccount]';
@@ -1143,6 +1145,54 @@ sub invoice_pdf {
 
 }
 
+sub legacy_invoice {
+  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 $legacyinvnum = $p->{'legacyinvnum'};
+
+  my $legacy_cust_bill = qsearchs('legacy_cust_bill', {
+    'legacyinvnum' => $legacyinvnum,
+    'custnum'      => $custnum,
+  }) or return { 'error' => "Can't find legacyinvnum" };
+
+  #my %return;
+
+  return { 'error'        => '',
+           'legacyinvnum' => $legacyinvnum,
+           'legacyid'     => $legacy_cust_bill->legacyid,
+           'invoice_html' => $legacy_cust_bill->content_html,
+         };
+
+}
+
+sub legacy_invoice_pdf {
+  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 $legacyinvnum = $p->{'legacyinvnum'};
+
+  my $legacy_cust_bill = qsearchs('legacy_cust_bill', {
+    'legacyinvnum' => $legacyinvnum,
+    'custnum'      => $custnum,
+  }) or return { 'error' => "Can't find legacyinvnum" };
+
+  #my %return;
+
+  return { 'error'        => '',
+           'legacyinvnum' => $legacyinvnum,
+           'legacyid'     => $legacy_cust_bill->legacyid,
+           'invoice_pdf'  => $legacy_cust_bill->content_pdf,
+         };
+
+}
+
 sub invoice_logo {
   my $p = shift;
 
@@ -1187,6 +1237,7 @@ sub list_invoices {
     or return { 'error' => "unknown custnum $custnum" };
 
   my @cust_bill = $cust_main->cust_bill;
+  my @legacy_cust_bill = $cust_main->legacy_cust_bill;
 
   my $balance = 0;
 
@@ -1196,18 +1247,32 @@ sub list_invoices {
               map {
                     my $owed = $_->owed;
                     $balance += $owed;
-                    +{ 'invnum'     => $_->invnum,
-                       '_date'      => $_->_date,
-                       'date'       => time2str("%b %o, %Y", $_->_date),
-                       'date_short' => time2str("%m-%d-%Y",  $_->_date),
-                       'previous'   => sprintf('%.2f', ($_->previous)[0]),
-                       'charged'    => sprintf('%.2f', $_->charged),
-                       'owed'       => sprintf('%.2f', $owed),
-                       'balance'    => sprintf('%.2f', $balance),
+                    +{ 'invnum'       => $_->invnum,
+                       '_date'        => $_->_date,
+                       'date'         => time2str("%b %o, %Y", $_->_date),
+                       'date_short'   => time2str("%m-%d-%Y",  $_->_date),
+                       'previous'     => sprintf('%.2f', ($_->previous)[0]),
+                       'charged'      => sprintf('%.2f', $_->charged),
+                       'owed'         => sprintf('%.2f', $owed),
+                       'balance'      => sprintf('%.2f', $balance),
                      }
                   }
                   @cust_bill
-            ]
+            ],
+            'legacy_invoices' => [
+              map {
+                    +{ 'legacyinvnum' => $_->legacyinvnum,
+                       'legacyid'     => $_->legacyid,
+                       '_date'        => $_->_date,
+                       'date'         => time2str("%b %o, %Y", $_->_date),
+                       'date_short'   => time2str("%m-%d-%Y",  $_->_date),
+                       'charged'      => sprintf('%.2f', $_->charged),
+                       'has_content'  => (    length($_->content_pdf)
+                                           || length($_->content_html) ),
+                     }
+                  }
+                  @legacy_cust_bill
+            ],
           };
 }
 
@@ -2332,12 +2397,93 @@ sub reset_passwd {
 
   }
 
-  #we're verified.  now what?
+  #okay, we're verified, now create a unique session
+
+  my $reset_session = {
+    'svcnum' => $svc_acct->svcnum,
+  };
+
+  my $timeout = '1 hour'; #?
+
+  my $reset_session_id;
+  do {
+    $reset_session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
+  } until ( ! defined _cache->get("reset_passwd_$reset_session_id") ); #just in case
+
+  _cache->set( "reset_passwd_$reset_session_id", $reset_session, $timeout );
+
+  #email it
+
+  my $msgnum = $conf->config('selfservice-password_reset_msgnum', $cust_main->agentnum);
+  #die "selfservice-password_reset_msgnum unset" unless $msgnum;
+  return { 'error' => "selfservice-password_reset_msgnum unset" } unless $msgnum;
+  my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } );
+  my $error = $msg_template->send( 'cust_main'     => $cust_main,
+                                   'object'        => $svc_acct,
+                                   'substitutions' => {
+                                     'session_id' => $reset_session_id,
+                                   }
+                                 );
+  if ( $error ) {
+    return { 'error' => $error }; #????
+  }
 
   return { 'error' => '' };
 }
 
+sub check_reset_passwd {
+  my $p = shift;
+
+  my $conf = new FS::Conf;
+  my $verification = $conf->config('selfservice-password_reset_verification')
+    or return { 'error' => 'Password resets disabled' };
+
+  my $reset_session = _cache->get('reset_passwd_'. $p->{'session_id'})
+    or return { 'error' => "Can't resume session" }; #better error message
+
+  my $svcnum = $reset_session->{'svcnum'};
+
+  my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
+    or return { 'error' => "Service not found" };
+
+  return { 'error'    => '',
+           'username' => $svc_acct->username,
+         };
+
+}
+
+sub process_reset_passwd {
+  my $p = shift;
+
+  my $conf = new FS::Conf;
+  my $verification = $conf->config('selfservice-password_reset_verification')
+    or return { 'error' => 'Password resets disabled' };
+
+  return { 'error' => "New passwords don't match." }
+    if $p->{'new_password'} ne $p->{'new_password2'};
+
+  return { 'error' => 'Enter new password' }
+    unless length($p->{'new_password'});
+
+  my $reset_session = _cache->get('reset_passwd_'. $p->{'session_id'})
+    or return { 'error' => "Can't resume session" }; #better error message
+
+  my $svcnum = $reset_session->{'svcnum'};
+
+  my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
+    or return { 'error' => "Service not found" };
+
+  $svc_acct->_password($p->{'new_password'});
+  my $error = $svc_acct->replace();
+
+  my($label, $value) = $svc_acct->cust_svc->label;
+
+  return { 'error' => $error,
+           #'label' => $label,
+           #'value' => $value,
+         };
+
+}
 
 sub create_ticket {
   my $p = shift;