contacts can be shared among customers / "duplicate contact emails", RT#27943
authorIvan Kohler <ivan@freeside.biz>
Tue, 3 Feb 2015 15:18:45 +0000 (07:18 -0800)
committerIvan Kohler <ivan@freeside.biz>
Tue, 3 Feb 2015 15:18:45 +0000 (07:18 -0800)
19 files changed:
1  2 
FS/FS/Daemon/Preforking.pm
FS/FS/Record.pm
FS/FS/contact.pm
FS/FS/part_event/Condition/cust_bill_has_service.pm
FS/FS/part_event/Condition/has_cust_tag.pm
FS/FS/part_export/amazon_ec2.pm
FS/FS/part_export/cardfortress.pm
FS/FS/phone_avail.pm
FS/bin/freeside-cdrd
bin/cust_bill-credit_ship2
eg/table_template.pm
fs_selfservice/DEPLOY
httemplate/browse/discount.html
httemplate/docs/about.html
httemplate/edit/cust_main-contacts.html
httemplate/elements/popup_link.html
httemplate/elements/tr-fixed.html
httemplate/elements/tr-select-cust_location.html
httemplate/search/cust_msg.html

@@@ -96,6 -96,6 +96,7 @@@ sub daemon_run 
    #parent doesn't need to hold a DB connection open
    dbh->disconnect;
    undef $FS::UID::dbh;
++  undef $RT::Handle;
  
    server_spawn(MAX_PROCESSES);
    POE::Kernel->run();
diff --cc FS/FS/Record.pm
@@@ -876,6 -876,6 +876,7 @@@ sub qsearchs { # $result_record = &FS::
    my $table = $_[0];
    my(@result) = qsearch(@_);
    cluck "warning: Multiple records in scalar search ($table)"
++        #.join(' / ', map "$_=>".$_[1]->{$_}, keys %{ $_[1] } )
      if scalar(@result) > 1;
    #should warn more vehemently if the search was on a primary key?
    scalar(@result) ? ($result[0]) : ();
Simple merge
@@@ -44,13 -44,13 +44,13 @@@ sub condition_sql 
    my $servicenums =
      $class->condition_sql_option_option_integer('has_service');
  
--  my $sql = qq| 0 < ( SELECT COUNT(cs.svcpart)
++  my $sql = " 0 < ( SELECT COUNT(cs.svcpart)
       FROM cust_bill_pkg cbp, cust_svc cs
      WHERE cbp.invnum = cust_bill.invnum
        AND cs.pkgnum = cbp.pkgnum
        AND cs.svcpart IN $servicenums
    )
--  |;
++  ";
    return $sql;
  }
  
@@@ -16,7 -16,7 +16,6 @@@ sub eventtable_hashref 
      };
  }
  
--#something like this
  sub option_fields {
    (
      'tagnum'  => { 'label'    => 'Customer tag',
@@@ -8,10 -8,10 +8,12 @@@ use FS::Record qw( qsearchs )
  use FS::svc_external;
  
  tie my %options, 'Tie::IxHash',
--  'access_key' => { label => 'AWS access key', },
--  'secret_key' => { label => 'AWS secret key', },
--  'ami'        => { label => 'AMI', 'default' => 'ami-ff46a796', },
--  'keyname'    => { label => 'Keypair name', },
++  'access_key'   => { label => 'AWS access key', },
++  'secret_key'   => { label => 'AWS secret key', },
++  'ami'          => { label => 'AMI', 'default' => 'ami-ff46a796', },
++  'keyname'      => { label => 'Keypair name', },
++  'region'       => { label => 'Region', },
++  'InstanceType' => { label => 'Instance Type', },
    #option to turn off (or on) ip address allocation
  ;
  
@@@ -38,6 -38,6 +40,7 @@@ sub _export_insert 
      $svc_external->svcnum,
      $self->option('ami'),
      $self->option('keyname'),
++    $self->option('InstanceType'),
    );
    ref($err_or_queue) ? '' : $err_or_queue;
  }
@@@ -96,31 -96,31 +99,35 @@@ sub amazon_ec2_queue 
    };
    $queue->insert( $self->option('access_key'),
                    $self->option('secret_key'),
++                  $self->option('region'),
                    @_
                  )
      or $queue;
  }
  
  sub amazon_ec2_new {
--  my( $access_key, $secret_key, @rest ) = @_;
++  my( $access_key, $secret_key, $region, @rest ) = @_;
  
    eval 'use Net::Amazon::EC2;';
    die $@ if $@;
  
    my $ec2 = new Net::Amazon::EC2 'AWSAccessKeyId'  => $access_key,
--                                 'SecretAccessKey' => $secret_key;
--
++                                 'SecretAccessKey' => $secret_key,
++                                 'region'          => $region || 'us-east-1',
++                                ;
    ( $ec2, @rest );
  }
  
  sub amazon_ec2_insert { #subroutine, not method
--  my( $ec2, $svcnum, $ami, $keyname ) = amazon_ec2_new(@_);
--
--  my $reservation_info = $ec2->run_instances( 'ImageId'  => $ami,
--                                              'KeyName'  => $keyname,
--                                              'MinCount' => 1,
--                                              'MaxCount' => 1,
--                                            );
++  my( $ec2, $svcnum, $ami, $keyname, $InstanceType ) = amazon_ec2_new(@_);
++
++  my $reservation_info = $ec2->run_instances(
++    'ImageId'      => $ami,
++    'KeyName'      => $keyname,
++    'InstanceType' => $InstanceType || 'm1.small',
++    'MinCount'     => 1,
++    'MaxCount'     => 1,
++  );
  
    my $instance_id = $reservation_info->instances_set->[0]->instance_id;
  
@@@ -28,6 -28,6 +28,7 @@@ sub _export_insert 
    my $ssh = Net::OpenSSH->new( $self->machine,
                                 default_stdin_fh => $def_in );
  
++  #capture2 and return STDERR, its probably useful if there's a problem
    my $private_key = $ssh->capture(
      { 'stdin_data' => $svc_acct->_password. "\n" },
      '/usr/local/bin/merchant_create', map $svc_acct->$_, qw( username finger )
@@@ -67,6 -67,6 +68,7 @@@ sub _export_delete 
    my $ssh = Net::OpenSSH->new( $self->machine,
                                 default_stdin_fh => $def_in );
  
++  #capture2 and return STDERR, its probably useful if there's a problem
    my $unused_output = $ssh->capture(
      '/usr/local/bin/merchant_disable', map $svc_acct->$_, qw( username )
    );
@@@ -283,8 -283,8 +283,8 @@@ sub _upgrade_data 
    my $sth = dbh->prepare(
      'UPDATE phone_avail SET svcnum = NULL
         WHERE svcnum IS NOT NULL
--         AND 0 = ( SELECT COUNT(*) FROM svc_phone
--                     WHERE phone_avail.svcnum = svc_phone.svcnum )'
++         AND NOT EXISTS ( SELECT 1 FROM svc_phone
++                            WHERE phone_avail.svcnum = svc_phone.svcnum )'
    ) or die dbh->errstr;
  
    $sth->execute or die $sth->errstr;
@@@ -120,10 -120,10 +120,10 @@@ while (1) 
  sub _shouldrun {
  
    my $extra_sql =
--    ' AND 0 < ( SELECT COUNT(*) FROM cust_pkg
--                  WHERE cust_pkg.pkgpart = part_pkg.pkgpart
--                    AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
--              )
++    ' AND EXISTS ( SELECT 1 FROM cust_pkg
++                     WHERE cust_pkg.pkgpart = part_pkg.pkgpart
++                       AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
++                 )
      ';
  
    my @part_pkg =
@@@ -193,16 -193,16 +193,17 @@@ foreach my $cust_bill ( @cust_bill ) 
    my $cur_cr = 0;
    $cur_cr += $_->amount foreach $cust_bill->cust_credited;
    $cur_cr = '' if $cur_cr == 0;
++
++  next if $cur_cr > 0 && $opt_k;
++
    if ( $opt_p ) {
      #print $cust_bill->invnum. ','. $cust_bill->custnum. ",$tax,$credit,$cr_percent%\n";
++#    print $cust_bill->invnum. ','. $cust_bill->custnum. ',"'.
++#          $cust_bill->cust_main->name. '",'. "$tax,$credit,$cur_cr\n";
      print $cust_bill->invnum. ','. $cust_bill->custnum. ',"'.
--          $cust_bill->cust_main->name. '",'. "$tax,$credit,$cur_cr\n";
++          $cust_bill->cust_main->name. '",'. "$tax,$credit\n";
    }
  
--  next if $cur_cr > 0 && $opt_k;
--
--#COMMENTING OUT ALL DANGEROUS STUFF
--#
  #  if ( $opt_m && ! $opt_r ) {
  #
  #    my $msg_template = qsearchs('msg_template', { 'msgnum' => $opt_m } )
  #           " custnum ". $cust_bill->custnum. ": $error\n";
  #    }
  #  }
--#
--#  if ( $opt_c ) {
--#    my $cust_credit = new FS::cust_credit {
--#      'custnum'   => $cust_main->custnum,
--#      'amount'    => $credit,
--#      'reasonnum' => $opt_c,
--#    };
--#    my $error = $cust_credit->insert;
--#    if ( $error ) {
--#      warn "error inserting credit: $error\n";
--#    }
--#    my $cust_credit_bill = new FS::cust_credit_bill {
--#      'crednum' => $cust_credit->crednum,
--#      'invnum'  => $cust_bill->invnum,
--#      'amount'  => $credit,
--#    };
--#    my $aerror = $cust_credit_bill->insert;
--#    if ( $aerror ) {
--#      warn "error applying credit to invnum ". $cust_bill->invnum. ": $aerror\n";
--#    }
--#  }
--#
++
++  if ( $opt_c ) {
++    my $cust_credit = new FS::cust_credit {
++      'custnum'   => $cust_main->custnum,
++      'amount'    => $credit,
++      'reasonnum' => $opt_c,
++    };
++    my $error = $cust_credit->insert;
++    if ( $error ) {
++      warn "error inserting credit: $error\n";
++    }
++    my $cust_credit_bill = new FS::cust_credit_bill {
++      'crednum' => $cust_credit->crednum,
++      'invnum'  => $cust_bill->invnum,
++      'amount'  => $credit,
++    };
++    my $aerror = $cust_credit_bill->insert;
++    if ( $aerror ) {
++      warn "error applying credit to invnum ". $cust_bill->invnum. ": $aerror\n";
++    }
++  }
++
  #  if ( $opt_e && ! $opt_r ) {
  #    eval { $cust_bill->email };
  #    if ( $@ ) {
@@@ -1,7 -1,7 +1,7 @@@
  package FS::table_name;
++use base qw( FS::Record );
  
  use strict;
--use base qw( FS::Record );
  use FS::Record qw( qsearch qsearchs );
  
  =head1 NAME
@@@ -11,7 -11,7 +11,8 @@@ perl Makefile.PL && make && make instal
  cd ..
  
  #( cd ..; make deploy; cd fs_selfservice )
--( cd ..; make clean; make configure-rt; make install-perl-modules; /etc/init.d/freeside restart; cd fs_selfservice )
++#( cd ..; make clean; make configure-rt; make install-perl-modules; /etc/init.d/freeside restart; cd fs_selfservice )
++( cd ..; make clean; make configure-rt; make install-perl-modules; make deploy; cd fs_selfservice )
  
  #cp /home/ivan/freeside/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount
  #chown freeside /var/www/MyAccount/*.cgi
@@@ -8,8 -8,8 +8,9 @@@
                   'count_query' => 'SELECT COUNT(*) FROM discount',
                   'disableable' => 1,
                   'disabled_statuspos' => 1,
--                 'header'      => [ 'Name', 'Class', 'Discount', ],
++                 'header'      => [ 'Name', 'Comment', 'Class', 'Discount', ],
                   'fields'      => [ 'name',
++                                    'comment',
                                      'classname',
                                      'description',
                                    ],
@@@ -56,7 -56,7 +56,7 @@@ GNU <b>Affero</b> General Public Licens
  
  % unless ( $agentnum ) {
    <CENTER>
--  <FONT SIZE="-3">"" - R. Hunter</FONT>
++  <FONT SIZE="-3">"Half the world's a desert / Cannibals eat human brains for dessert" - D. Zero</FONT>
    </CENTER>
  % }
  
@@@ -11,6 -11,6 +11,7 @@@
         { 'field'             => 'contactnum',
           'type'              => 'contact',
           'colspan'           => 6,
++         'custnum'           => $custnum,
           'm2m_method'        => 'cust_contact',
           'm2m_dstcol'        => 'contactnum',   
           'm2_label'          => ' ', #'Contact',
@@@ -2,9 -2,9 +2,9 @@@
  
  Example:
  
--  include('/elements/init_overlib.html')
++  <& /elements/init_overlib.html &>
  
--  include( '/elements/popup_link.html', { #hashref or a list, either way is fine
++  <& /elements/popup_link.html', { #hashref or a list, either way is fine
  
      #required
      'action'         => 'content.html', # uri for content of popup
@@@ -23,7 -23,7 +23,8 @@@
      'aname'          => "target", # link NAME= value, useful for #targets
      'target'         => '_parent',
      'style'          => 'css-attribute:value',
--  } )
++  }
++  &>
  
  </%doc>
  % if ($params->{'action'} && $label) {
@@@ -1,6 -1,6 +1,6 @@@
  <% include('tr-td-label.html', @_ ) %>
  
--  <TD BGCOLOR="#dddddd" <% $style %>><% $value %></TD>
++  <TD BGCOLOR="#dddddd" <% $style %> <% $colspan %>><% $value %></TD>
  
  </TR>
  
@@@ -10,7 -10,7 +10,9 @@@
  
  my %opt = @_;
  
--my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
++my $style = $opt{'cell_style'} ? ' STYLE="'. $opt{'cell_style'}. '" ' : '';
++
++my $colspan = $opt{'colspan'} ? ' COLSPAN="'. $opt{'colspan'}. '" ' : '';
  
  my $value = $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'};
  $value = $opt{'prefix'} . $value if defined($opt{'prefix'});
@@@ -287,6 -287,6 +287,8 @@@ if ( $locationnum && $locationnum > 0 
  $cust_location->coord_auto('Y');
  
  my $location_sort = sub {
++  #enabled w/label_prefix _location #    $a->locationname cmp $b->locationname
++                                    # or 
          $a->country   cmp $b->country
    or lc($a->city)     cmp lc($b->city)
    or lc($a->address1) cmp lc($b->address1)
@@@ -47,7 -47,7 +47,7 @@@
                            ],
         'html_init'     => $html_init,
         'really_disable_download' => 1,
--       @_
++       @_ #why?
  &>
  <%init>
  #hmm...
@@@ -71,7 -71,7 +71,7 @@@ if ( $cgi->param('msgtype') =~ /^(\w+)$
    push @where, "msgtype = '$1'";
  }
  if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
--  push @where, "custnum = $1";
++  push @where, "cust_msg.custnum = $1";
  }
  my ($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, '');
  push @where, "(_date >= $beginning AND _date <= $ending)";