diff options
Diffstat (limited to 'FS')
| -rw-r--r-- | FS/FS/ClientAPI/Agent.pm | 80 | ||||
| -rw-r--r-- | FS/FS/ClientAPI/MyAccount.pm | 140 | ||||
| -rw-r--r-- | FS/FS/ClientAPI/Signup.pm | 2 | ||||
| -rw-r--r-- | FS/FS/Conf.pm | 9 | ||||
| -rw-r--r-- | FS/FS/cust_main.pm | 37 | 
5 files changed, 205 insertions, 63 deletions
| diff --git a/FS/FS/ClientAPI/Agent.pm b/FS/FS/ClientAPI/Agent.pm index 212faaa6b..1cc11d536 100644 --- a/FS/FS/ClientAPI/Agent.pm +++ b/FS/FS/ClientAPI/Agent.pm @@ -6,12 +6,14 @@ use strict;  use vars qw($cache);  use Digest::MD5 qw(md5_hex);  use Cache::SharedMemoryCache; #store in db? -use FS::Record qw(qsearchs); # qsearch); +use FS::Record qw(qsearchs qsearch dbdef dbh);  use FS::agent; +use FS::cust_main;  use FS::ClientAPI;  FS::ClientAPI->register_handlers(    'Agent/agent_login'          => \&agent_login, +  'Agent/agent_logout'         => \&agent_logout,    'Agent/agent_info'           => \&agent_info,    'Agent/agent_list_customers' => \&agent_list_customers,  ); @@ -52,6 +54,16 @@ sub agent_login {    };  } +sub agent_logout { +  my $p = shift; +  if ( $p->{'session_id'} ) { +    $cache->remove($p->{'session_id'}); +    return { 'error' => '' }; +  } else { +    return { 'error' => "Can't resume session" }; #better error message +  } +} +  sub agent_info {    my $p = shift; @@ -92,12 +104,76 @@ sub agent_list_customers {    my @cust_main = (); -  warn $p->{'susp'}; +  #warn $p->{'search'}; +  if ( $p->{'search'} =~ /^\s*(\d+)\s*$/ ) { # customer # search +    push @cust_main, qsearch('cust_main', { 'agentnum' => $agentnum, +                                            'custnum'  => $1         } ); +  } elsif ( $p->{'search'} =~ /^\s*(\S.*\S)\s*$/ ) { #value search +    my $value = lc($1); +    my $q_value = dbh->quote($value); + +    #exact +    my $sql = " AND ( LOWER(last) = $q_value OR LOWER(company) = $q_value"; +    $sql .= " OR LOWER(ship_last) = $q_value OR LOWER(ship_company) = $q_value" +      if defined dbdef->table('cust_main')->column('ship_last'); +    $sql .= ' )'; + +    push @cust_main, qsearch( 'cust_main', +                              { 'agentnum' => $agentnum }, +                              '', +                              $sql +                            ); + +    unless ( @cust_main ) { +      warn "no exact match, trying substring/fuzzy\n"; + +      #still some false laziness w/ search/cust_main.cgi + +      #substring +      push @cust_main, qsearch( 'cust_main', +                                { 'agentnum' => $agentnum, +                                  'last'     => { 'op'    => 'ILIKE', +                                                  'value' => "%$q_value%" } } ); + +      push @cust_main, qsearch( 'cust_main', +                                { 'agentnum'  => $agentnum, +                                  'ship_last' => { 'op'    => 'ILIKE', +                                                   'value' => "%$q_value%" } } ) +        if defined dbdef->table('cust_main')->column('ship_last'); + +      push @cust_main, qsearch( 'cust_main', +                                { 'agentnum' => $agentnum, +                                  'company'  => { 'op'    => 'ILIKE', +                                                  'value' => "%$q_value%" } } ); + +      push @cust_main, qsearch( 'cust_main', +                                { 'agentnum'     => $agentnum, +                                  'ship_company' => { 'op' => 'ILIKE', +                                                   'value' => "%$q_value%" } } ) +        if defined dbdef->table('cust_main')->column('ship_last'); + +      #fuzzy +      push @cust_main, FS::cust_main->fuzzy_search( +        { 'last'     => $value }, +        { 'agentnum' => $agentnum } +      ); +      push @cust_main, FS::cust_main->fuzzy_search( +        { 'company'  => $value }, +        { 'agentnum' => $agentnum } +      ); + +    } +  } +  #aggregate searches    push @cust_main,      map $agent->$_(), map $_.'_cust_main',        grep $p->{$_}, qw( prospect active susp cancel ); +  #eliminate dups? +  my %saw = (); +  @cust_main = grep { !$saw{$_->custnum}++ } @cust_main; +    { customers => [ map {                           my $cust_main = $_;                           my $hashref = $cust_main->hashref; diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 639cb7b9b..34dad3870 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -109,23 +109,8 @@ sub logout {  sub customer_info {    my $p = shift; -  my($session, $custnum, $context); -  if ( $p->{'session_id'} ) { -    $context = 'customer'; -    $session = $cache->get($p->{'session_id'}) -      or return { 'error' => "Can't resume session" }; #better error message -    $custnum = $session->{'custnum'}; -  } elsif ( $p->{'agent_session_id'} ) { -    $context = 'agent'; -    my $agent_cache = new Cache::SharedMemoryCache( { -      'namespace' => 'FS::ClientAPI::Agent', -    } ); -    $session = $agent_cache->get($p->{'agent_session_id'}) -      or return { 'error' => "Can't resume session" }; #better error message -    $custnum = $p->{'custnum'}; -  } else { -    return { 'error' => "Can't resume session" }; #better error message -  } +  my($context, $session, $custnum) = _custoragent_session_custnum($p); +  return { 'error' => $session } if $context eq 'error';    my %return;    if ( $custnum ) { #customer record @@ -451,31 +436,42 @@ sub cancel {  sub list_pkgs {    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($context, $session, $custnum) = _custoragent_session_custnum($p); +  return { 'error' => $session } if $context eq 'error'; -  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) +  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" };    #return { 'cust_pkg' => [ map { $_->hashref } $cust_main->ncancelled_pkgs ] }; +  my $conf = new FS::Conf; +    { 'svcnum'   => $session->{'svcnum'}, +    'custnum'  => $custnum,      'cust_pkg' => [ map {                            { $_->hash,                              $_->part_pkg->hash,                              part_svc =>                                [ map $_->hashref, $_->available_part_svc ],                              cust_svc =>  -                              [ map { { $_->hash, -                                        label => [ $_->label ], -                                      } +                              [ map { my $ref = { $_->hash, +                                                  label => [ $_->label ], +                                                }; +                                      $ref->{_password} = $_->svc_x->_password +                                        if $context eq 'agent' +                                        && $conf->exists('agent-showpasswords') +                                        && $_->part_svc->svcdb eq 'svc_acct'; +                                      $ref;                                      } $_->cust_svc                                ],                            };                          } $cust_main->ncancelled_pkgs                    ], +    'small_custview' => +      small_custview( $cust_main, $conf->config('defaultcountry') ),    };  } @@ -483,28 +479,11 @@ sub list_pkgs {  sub order_pkg {    my $p = shift; -  my($session, $custnum, $context); - -  if ( $p->{'session_id'} ) { -    $context = 'customer'; -    $session = $cache->get($p->{'session_id'}) -      or return { 'error' => "Can't resume session" }; #better error message -    $custnum = $session->{'custnum'}; -  } elsif ( $p->{'agent_session_id'} ) { -    $context = 'agent'; -    my $agent_cache = new Cache::SharedMemoryCache( { -      'namespace' => 'FS::ClientAPI::Agent', -    } ); -    $session = $agent_cache->get($p->{'agent_session_id'}) -      or return { 'error' => "Can't resume session" }; #better error message -    $custnum = $p->{'custnum'}; -  } else { -    return { 'error' => "Can't resume session" }; #better error message -  } +  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" }; @@ -632,12 +611,12 @@ sub cancel_pkg {  sub provision_acct {    my $p = shift; -  my $session = $cache->get($p->{'session_id'}) -    or return { 'error' => "Can't resume session" }; #better error message +  my($context, $session, $custnum) = _custoragent_session_custnum($p); +  return { 'error' => $session } if $context eq 'error'; -  my $custnum = $session->{'custnum'}; - -  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) +  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 $pkgnum = $p->{'pkgnum'}; @@ -671,12 +650,12 @@ sub provision_acct {  sub part_svc_info {    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($context, $session, $custnum) = _custoragent_session_custnum($p); +  return { 'error' => $session } if $context eq 'error'; -  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) +  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 $pkgnum = $p->{'pkgnum'}; @@ -693,11 +672,14 @@ sub part_svc_info {      or return { 'error' => "unknown svcpart $svcpart for pkgnum $pkgnum" };    my $part_svc = $pkg_svc->part_svc; +  my $conf = new FS::Conf; +    return {      'svc'     => $part_svc->svc,      'svcdb'   => $part_svc->svcdb,      'pkgnum'  => $pkgnum,      'svcpart' => $svcpart, +    'custnum' => $custnum,      'security_phrase' => 0, #XXX !      'svc_acct_pop'    => [], #XXX ! @@ -705,6 +687,10 @@ sub part_svc_info {      'init_popstate'   => '',      'popac'           => '',      'acstate'         => '', + +    'small_custview' => +      small_custview( $cust_main, $conf->config('defaultcountry') ), +    };  } @@ -712,12 +698,12 @@ sub part_svc_info {  sub unprovision_svc {    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($context, $session, $custnum) = _custoragent_session_custnum($p); +  return { 'error' => $session } if $context eq 'error'; -  my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) +  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 $svcnum = $p->{'svcnum'}; @@ -728,11 +714,47 @@ sub unprovision_svc {    return { 'error' => "Service $svcnum does not belong to customer $custnum" }      unless $cust_svc->cust_pkg->custnum == $custnum; +  my $conf = new FS::Conf; +    return { 'svc'   => $cust_svc->part_svc->svc, -           'error' => $cust_svc->cancel +           'error' => $cust_svc->cancel, +           'small_custview' => +             small_custview( $cust_main, $conf->config('defaultcountry') ),           };  } +#-- + +sub _custoragent_session_custnum { +  my $p = shift; + +  my($context, $session, $custnum); +  if ( $p->{'session_id'} ) { + +    $context = 'customer'; +    $session = $cache->get($p->{'session_id'}) +      or return { 'error' => "Can't resume session" }; #better error message +    $custnum = $session->{'custnum'}; + +  } elsif ( $p->{'agent_session_id'} ) { + +    $context = 'agent'; +    my $agent_cache = new Cache::SharedMemoryCache( { +      'namespace' => 'FS::ClientAPI::Agent', +    } ); +    $session = $agent_cache->get($p->{'agent_session_id'}) +      or return { 'error' => "Can't resume session" }; #better error message +    $custnum = $p->{'custnum'}; + +  } else { +    return { 'error' => "Can't resume session" }; #better error message +  } + +  ($context, $session, $custnum); + +} + +  1; diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index 81ed5e65c..bdcd2fbf1 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -76,7 +76,7 @@ sub signup_info {      'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'),      'msgcat' => { map { $_=>gettext($_) } qw( -      passwords_dont_match invalid_card unknown_card_type not_a +      passwords_dont_match invalid_card unknown_card_type not_a empty_password      ) },      'statedefault' => $conf->config('statedefault') || 'CA', diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index bfef62807..c8f0d81af 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -759,7 +759,7 @@ httemplate/docs/config.html    {      'key'         => 'showpasswords',      'section'     => 'UI', -    'description' => 'Display unencrypted user passwords in the web interface', +    'description' => 'Display unencrypted user passwords in the backend (employee) web interface',      'type'        => 'checkbox',    }, @@ -1276,6 +1276,13 @@ httemplate/docs/config.html      'type'        => 'text',    }, +  { +    'key'         => 'agent-showpasswords', +    'section'     => '', +    'description' => 'Display unencrypted user passwords in the agent (reseller) interface', +    'type'        => 'checkbox', +  }, +  );  1; diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 58d1a28f5..1540b61a3 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -13,6 +13,7 @@ BEGIN {  }  use Date::Format;  #use Date::Manip; +use String::Approx qw(amatch);  use Business::CreditCard;  use FS::UID qw( getotaker dbh );  use FS::Record qw( qsearchs qsearch dbdef ); @@ -2949,6 +2950,42 @@ sub cancel_sql { "            )  "; } +=item fuzzy_search FUZZY_HASHREF [ HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ ] + +Performs a fuzzy (approximate) search and returns the matching FS::cust_main +records.  Currently, only I<last> or I<company> may be specified (the +appropriate ship_ field is also searched if applicable). + +Additional options are the same as FS::Record::qsearch + +=cut + +sub fuzzy_search { +  my( $self, $fuzzy, $hash, @opt) = @_; +  #$self +  $hash ||= {}; +  my @cust_main = (); + +  check_and_rebuild_fuzzyfiles(); +  foreach my $field ( keys %$fuzzy ) { +    my $sub = \&{"all_$field"}; +    my %match = (); +    $match{$_}=1 foreach ( amatch($fuzzy->{$field}, ['i'], @{ &$sub() } ) ); + +    foreach ( keys %match ) { +      push @cust_main, qsearch('cust_main', { %$hash, $field=>$_}, @opt); +      push @cust_main, qsearch('cust_main', { %$hash, "ship_$field"=>$_}, @opt) +        if defined dbdef->table('cust_main')->column('ship_last'); +    } +  } + +  my %saw = (); +  @cust_main = grep { !$saw{$_->custnum}++ } @cust_main; + +  @cust_main; + +} +  =back  =head1 SUBROUTINES | 
