X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main_Mixin.pm;h=f584b415eb98e66ec38dc47ae115b1a395e0099b;hb=010c8080a423af31fe92082c271ad8b261450393;hp=b446d69651348ed0972525ddb1ab547a1e9cc6cf;hpb=6c9cd1c36adbb9fc950fcf0a0b269fa6f16838a1;p=freeside.git diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm index b446d6965..f584b415e 100644 --- a/FS/FS/cust_main_Mixin.pm +++ b/FS/FS/cust_main_Mixin.pm @@ -131,9 +131,12 @@ linked to a customer. sub country_full { my $self = shift; - $self->cust_linked - ? FS::cust_main::country_full($self) - : $self->cust_unlinked_msg; + if ( $self->locationnum ) { # cust_pkg has this + my $location = FS::cust_location->by_key($self->locationnum); + $location ? $location->country_full : ''; + } elsif ( $self->cust_linked ) { + $self->cust_main->bill_country_full; + } } =item invoicing_list_emailonly @@ -388,6 +391,7 @@ in the job fail, the entire job will abort and return an error. use Storable qw(thaw); use MIME::Base64; use Data::Dumper qw(Dumper); +use Digest::SHA qw(sha1); # for duplicate checking sub email_search_result { my($class, $param) = @_; @@ -408,10 +412,8 @@ sub email_search_result { or die "msgnum $msgnum not found\n"; } - $param->{'payby'} = [ split(/\0/, $param->{'payby'}) ] - unless ref($param->{'payby'}); - my $sql_query = $class->search($param->{'search'}); + $sql_query->{'select'} = $sql_query->{'table'} . '.*'; my $count_query = delete($sql_query->{'count_query'}); my $count_sth = dbh->prepare($count_query) @@ -423,7 +425,9 @@ sub email_search_result { my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo my @retry_jobs = (); + my $dups = 0; my $success = 0; + my %sent_to = (); #eventually order+limit magic to reduce memory use? foreach my $obj ( qsearch($sql_query) ) { @@ -439,29 +443,45 @@ sub email_search_result { } my $cust_main = $obj->cust_main; - my @message; + tie my %message, 'Tie::IxHash'; if ( !$cust_main ) { next; # unlinked object; nothing else we can do } - + if ( $msg_template ) { - # XXX add support for other context objects? - @message = $msg_template->prepare( 'cust_main' => $cust_main ); + # Now supports other context objects. + %message = $msg_template->prepare( + 'cust_main' => $cust_main, + 'object' => $obj, + ); } else { - my $to = $cust_main->invoicing_list_emailonly_scalar; - next if !$to; + my @to = $cust_main->invoicing_list_emailonly; + next if !@to; - @message = ( + %message = ( 'from' => $from, - 'to' => $to, + 'to' => \@to, 'subject' => $subject, 'html_body' => $html_body, 'text_body' => $text_body, + 'custnum' => $cust_main->custnum, ); } #if $msg_template - $error = send_email( generate_email( @message ) ); + # For non-cust_main searches, we avoid duplicates based on message + # body text. + my $unique = $cust_main->custnum; + $unique .= sha1($message{'text_body'}) if $class ne 'FS::cust_main'; + if( $sent_to{$unique} ) { + # avoid duplicates + $dups++; + next; + } + + $sent_to{$unique} = 1; + + $error = send_email( generate_email( %message ) ); if($error) { # queue the sending of this message so that the user can see what we @@ -472,7 +492,7 @@ sub email_search_result { 'status' => 'failed', 'statustext' => $error, }; - $queue->insert(@message); + $queue->insert(%message); push @retry_jobs, $queue; } else { @@ -494,7 +514,7 @@ sub email_search_result { if(@retry_jobs) { # fail the job, but with a status message that makes it clear # something was sent. - return "Sent $success, failed ".scalar(@retry_jobs).". Failed attempts placed in job queue.\n"; + return "Sent $success, skipped $dups duplicate(s), failed ".scalar(@retry_jobs).". Failed attempts placed in job queue.\n"; } return ''; @@ -522,10 +542,46 @@ sub process_email_search_result { die "error loading FS::$table: $@\n" if $@; my $error = "FS::$table"->email_search_result( $param ); + dbh->commit; # save failed jobs before rethrowing the error die $error if $error; } +=item conf + +Returns a configuration handle (L) set to the customer's locale, +if they have one. If not, returns an FS::Conf with no locale. + +=cut + +sub conf { + my $self = shift; + return $self->{_conf} if (ref $self and $self->{_conf}); + my $cust_main = $self->cust_main; + my $conf = new FS::Conf { + 'locale' => ($cust_main ? $cust_main->locale : '') + }; + $self->{_conf} = $conf if ref $self; + return $conf; +} + +=item mt TEXT [, ARGS ] + +Localizes a text string (see L) for the customer's locale, +if they have one. + +=cut + +sub mt { + my $self = shift; + return $self->{_lh}->maketext(@_) if (ref $self and $self->{_lh}); + my $cust_main = $self->cust_main; + my $locale = $cust_main ? $cust_main->locale : ''; + my $lh = FS::L10N->get_handle($locale); + $self->{_lh} = $lh if ref $self; + return $lh->maketext(@_); +} + =back =head1 BUGS