From: Ivan Kohler Date: Tue, 3 Feb 2015 15:18:45 +0000 (-0800) Subject: contacts can be shared among customers / "duplicate contact emails", RT#27943 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=aeb90ade381fc3d5477db0334048c2af623fccfe;hp=167dbdad01e2c1b62fd9be43cc05212e8c874a02 contacts can be shared among customers / "duplicate contact emails", RT#27943 --- diff --git a/FS/FS/Daemon/Preforking.pm b/FS/FS/Daemon/Preforking.pm index 98b4fa68c..f3a39a6ed 100644 --- a/FS/FS/Daemon/Preforking.pm +++ b/FS/FS/Daemon/Preforking.pm @@ -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 --git a/FS/FS/Record.pm b/FS/FS/Record.pm index f8282c031..92fb89665 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -876,6 +876,7 @@ sub qsearchs { # $result_record = &FS::Record:qsearchs('table',\%hash); 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]) : (); diff --git a/FS/FS/contact.pm b/FS/FS/contact.pm index 07458c742..589fc7c19 100644 --- a/FS/FS/contact.pm +++ b/FS/FS/contact.pm @@ -464,6 +464,8 @@ sub replace { next; } + $contact_phone ||= new FS::contact_phone \%cp; + my %cpd = _parse_phonestring( $self->get($pf) ); $contact_phone->set( $_ => $cpd{$_} ) foreach keys %cpd; diff --git a/FS/FS/part_event/Condition/cust_bill_has_service.pm b/FS/FS/part_event/Condition/cust_bill_has_service.pm index 6e981ee03..898b08d10 100644 --- a/FS/FS/part_event/Condition/cust_bill_has_service.pm +++ b/FS/FS/part_event/Condition/cust_bill_has_service.pm @@ -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; } diff --git a/FS/FS/part_event/Condition/has_cust_tag.pm b/FS/FS/part_event/Condition/has_cust_tag.pm index cde933881..79bf2d303 100644 --- a/FS/FS/part_event/Condition/has_cust_tag.pm +++ b/FS/FS/part_event/Condition/has_cust_tag.pm @@ -16,7 +16,6 @@ sub eventtable_hashref { }; } -#something like this sub option_fields { ( 'tagnum' => { 'label' => 'Customer tag', diff --git a/FS/FS/part_export/amazon_ec2.pm b/FS/FS/part_export/amazon_ec2.pm index 06e2c238e..c1082a8aa 100644 --- a/FS/FS/part_export/amazon_ec2.pm +++ b/FS/FS/part_export/amazon_ec2.pm @@ -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 +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 +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; diff --git a/FS/FS/part_export/cardfortress.pm b/FS/FS/part_export/cardfortress.pm index 7ff728081..154f979b0 100644 --- a/FS/FS/part_export/cardfortress.pm +++ b/FS/FS/part_export/cardfortress.pm @@ -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 +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 ) ); diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index 2748686cc..f56878acf 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -697,6 +697,8 @@ some components specified by "select-.*.html", and a bunch more... =item select_label - Used with select_table, this is the field name of labels +=item select_allow_empty - Used with select_table, adds an empty option + =back =cut diff --git a/FS/FS/phone_avail.pm b/FS/FS/phone_avail.pm index 52bbdeb10..ae8526c3d 100644 --- a/FS/FS/phone_avail.pm +++ b/FS/FS/phone_avail.pm @@ -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; diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 06ce94848..71a61ad16 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -196,6 +196,7 @@ sub table_info { select_table => 'svc_domain', select_key => 'svcnum', select_label => 'domain', + select_allow_empty => 1, disable_inventory => 1, }, 'circuit_svcnum' => { label => 'Circuit', diff --git a/FS/bin/freeside-cdrd b/FS/bin/freeside-cdrd index 45d58789d..a3c67f919 100644 --- a/FS/bin/freeside-cdrd +++ b/FS/bin/freeside-cdrd @@ -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 = diff --git a/bin/cust_bill-credit_ship2 b/bin/cust_bill-credit_ship2 index c4d5169c1..a9a899c38 100755 --- a/bin/cust_bill-credit_ship2 +++ b/bin/cust_bill-credit_ship2 @@ -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 } ) @@ -216,28 +217,28 @@ foreach my $cust_bill ( @cust_bill ) { # " 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 ( $@ ) { diff --git a/eg/table_template.pm b/eg/table_template.pm index 0a6f85156..686bef6a8 100644 --- a/eg/table_template.pm +++ b/eg/table_template.pm @@ -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 diff --git a/fs_selfservice/DEPLOY b/fs_selfservice/DEPLOY index bedb5eca9..4e0f495f9 100755 --- a/fs_selfservice/DEPLOY +++ b/fs_selfservice/DEPLOY @@ -11,7 +11,8 @@ perl Makefile.PL && make && make install 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 diff --git a/httemplate/browse/discount.html b/httemplate/browse/discount.html index d3cf873d0..9b2298ae4 100644 --- a/httemplate/browse/discount.html +++ b/httemplate/browse/discount.html @@ -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', ], diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html index 80d9488b6..0f173f228 100644 --- a/httemplate/docs/about.html +++ b/httemplate/docs/about.html @@ -56,7 +56,7 @@ GNU Affero General Public License.
% unless ( $agentnum ) {
- "" - R. Hunter + "Half the world's a desert / Cannibals eat human brains for dessert" - D. Zero
% } diff --git a/httemplate/edit/cust_main-contacts.html b/httemplate/edit/cust_main-contacts.html index 9f0654608..3b7eb07d3 100644 --- a/httemplate/edit/cust_main-contacts.html +++ b/httemplate/edit/cust_main-contacts.html @@ -11,6 +11,7 @@ { 'field' => 'contactnum', 'type' => 'contact', 'colspan' => 6, + 'custnum' => $custnum, 'm2m_method' => 'cust_contact', 'm2m_dstcol' => 'contactnum', 'm2_label' => ' ', #'Contact', diff --git a/httemplate/edit/elements/part_svc_column.html b/httemplate/edit/elements/part_svc_column.html index 53cda859e..2bb4f5e41 100644 --- a/httemplate/edit/elements/part_svc_column.html +++ b/httemplate/edit/elements/part_svc_column.html @@ -140,7 +140,8 @@ that field. 'value_col' => $def->{'select_key'}, 'order_by' => dbdef->table($def->{'select_table'})->primary_key, 'multiple' => $def->{'multiple'}, - 'disable_empty' => 1, + 'disable_empty' => $def->{'select_allow_empty'} ? undef : 1, + 'empty_label' => $def->{'select_allow_empty'} ? ' ' : undef, 'curr_value' => $value, # these can be switched between multiple and singular, # so put the complete curr_value in an attribute diff --git a/httemplate/edit/quick-charge.html b/httemplate/edit/quick-charge.html index 83620a973..58c1b0a82 100644 --- a/httemplate/edit/quick-charge.html +++ b/httemplate/edit/quick-charge.html @@ -171,6 +171,7 @@ function bill_now_changed (what) { &> % } +% unless ($billed) { <% mt('Tax exempt') |h %> param('setuptax') ? 'CHECKED' : '' %>> @@ -179,6 +180,7 @@ function bill_now_changed (what) { <& /elements/tr-select-taxclass.html, 'curr_value' => $part_pkg->get('taxclass') &> <& /elements/tr-select-taxproduct.html, 'label' => emt('Tax product'), 'onclick' => 'parent.taxproductmagic(this);', 'curr_value' => $part_pkg->get('taxproductnum') &> +% } % } else { # new one-time charge diff --git a/httemplate/elements/popup_link.html b/httemplate/elements/popup_link.html index e5f8c61ca..2b6b187e9 100644 --- a/httemplate/elements/popup_link.html +++ b/httemplate/elements/popup_link.html @@ -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,8 @@ Example: 'aname' => "target", # link NAME= value, useful for #targets 'target' => '_parent', 'style' => 'css-attribute:value', - } ) + } + &> % if ($params->{'action'} && $label) { diff --git a/httemplate/elements/tr-fixed.html b/httemplate/elements/tr-fixed.html index 6904e3b30..373c0ab3a 100644 --- a/httemplate/elements/tr-fixed.html +++ b/httemplate/elements/tr-fixed.html @@ -1,6 +1,6 @@ <% include('tr-td-label.html', @_ ) %> - ><% $value %> + <% $colspan %>><% $value %> @@ -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'}); diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html index abaaa5b42..7a5b43bb8 100644 --- a/httemplate/elements/tr-select-cust_location.html +++ b/httemplate/elements/tr-select-cust_location.html @@ -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) diff --git a/httemplate/search/cust_msg.html b/httemplate/search/cust_msg.html index 486c7b09c..d5b865c3b 100644 --- a/httemplate/search/cust_msg.html +++ b/httemplate/search/cust_msg.html @@ -47,7 +47,7 @@ ], 'html_init' => $html_init, 'really_disable_download' => 1, - @_ + @_ #why? &> <%init> #hmm... @@ -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)";