X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main_Mixin.pm;h=bdad511fa696950625f0cba6efcc3f4d1c5ae0e9;hb=4df3cb3192930c482c07c8d8e077a736244d4fc6;hp=d493060f0c7cf445b4b0ccaaa35994ffda8f8426;hpb=fb4ab1073f0d15d660c6cdc4e07afebf68ef3924;p=freeside.git diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm index d493060f0..bdad511fa 100644 --- a/FS/FS/cust_main_Mixin.pm +++ b/FS/FS/cust_main_Mixin.pm @@ -2,11 +2,12 @@ package FS::cust_main_Mixin; use strict; use vars qw( $DEBUG $me ); -use Carp qw( confess ); +use Carp qw( confess carp cluck ); use FS::UID qw(dbh); use FS::cust_main; use FS::Record qw( qsearch qsearchs ); use FS::Misc qw( send_email generate_email ); +use HTML::Entities; $DEBUG = 0; $me = '[FS::cust_main_Mixin]'; @@ -37,6 +38,7 @@ sub cust_linked { $_[0]->custnum; } sub cust_main { my $self = shift; + cluck ref($self). '->cust_main called' if $DEBUG; $self->cust_linked ? qsearchs('cust_main', {custnum => $self->custnum}) : ''; } @@ -131,9 +133,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 @@ -230,12 +235,26 @@ linked to a customer. =cut sub ucfirst_cust_status { + carp "ucfirst_cust_status deprecated, use cust_status_label"; + local($FS::cust_main::ucfirst_nowarn) = 1; my $self = shift; $self->cust_linked ? ucfirst( $self->cust_status(@_) ) : $self->cust_unlinked_msg; } +=item cust_status_label + +=cut + +sub cust_status_label { + my $self = shift; + + $self->cust_linked + ? FS::cust_main::cust_status_label($self) + : $self->cust_unlinked_msg; +} + =item cust_statuscolor Given an object that contains fields from cust_main (say, from a JOINed @@ -388,6 +407,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) = @_; @@ -409,6 +429,7 @@ sub email_search_result { } 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) @@ -438,32 +459,23 @@ 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( $sent_to{$cust_main->custnum} ) { - # avoid duplicates - $dups++; - next; - } - - $sent_to{$cust_main->custnum} = 1; - if ( $msg_template ) { - # XXX add support for other context objects? - # If we do that, handling of "duplicates" will - # have to be smarter. Currently we limit to - # one message per custnum because they'd all - # be identical. - @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; next if !@to; - @message = ( + %message = ( 'from' => $from, 'to' => \@to, 'subject' => $subject, @@ -473,7 +485,19 @@ sub email_search_result { ); } #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 @@ -484,7 +508,7 @@ sub email_search_result { 'status' => 'failed', 'statustext' => $error, }; - $queue->insert(@message); + $queue->insert(%message); push @retry_jobs, $queue; } else { @@ -516,7 +540,7 @@ sub process_email_search_result { my $job = shift; #warn "$me process_re_X $method for job $job\n" if $DEBUG; - my $param = thaw(decode_base64(shift)); + my $param = shift; warn Dumper($param) if $DEBUG; $param->{'job'} = $job; @@ -534,6 +558,7 @@ 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; } @@ -573,6 +598,67 @@ sub mt { return $lh->maketext(@_); } +=item time2str_local FORMAT, TIME[, ESCAPE] + +Localizes a date (see L) for the customer's locale. + +FORMAT can be a L string, or one of these special words: + +- "short": the value of the "date_format" config setting for the customer's + locale, defaulting to "%x". +- "rdate": the same as "short" except that the default has a four-digit year. +- "long": the value of the "date_format_long" config setting for the + customer's locale, defaulting to "%b %o, %Y". + +ESCAPE, if specified, is one of "latex" or "html", and will escape non-ASCII +characters and convert spaces to nonbreaking spaces. + +=cut + +sub time2str_local { + # renamed so that we don't have to change every single reference to + # time2str everywhere + my $self = shift; + my ($format, $time, $escape) = @_; + return '' unless $time > 0; # work around time2str's traditional stupidity + + $self->{_date_format} ||= {}; + if (!exists($self->{_dh})) { + my $cust_main = $self->cust_main; + my $locale = $cust_main->locale if $cust_main; + $locale ||= 'en_US'; + my %info = FS::Locales->locale_info($locale); + my $dh = eval { Date::Language->new($info{'name'}) } || + Date::Language->new(); # fall back to English + $self->{_dh} = $dh; + } + + if ($format eq 'short') { + $format = $self->{_date_format}->{short} + ||= $self->conf->config('date_format') || '%x'; + } elsif ($format eq 'rdate') { + $format = $self->{_date_format}->{rdate} + ||= $self->conf->config('date_format') || '%m/%d/%Y'; + } elsif ($format eq 'long') { + $format = $self->{_date_format}->{long} + ||= $self->conf->config('date_format_long') || '%b %o, %Y'; + } + + # actually render the date + my $string = $self->{_dh}->time2str($format, $time); + + if ($escape) { + if ($escape eq 'html') { + $string = encode_entities($string); + $string =~ s/ +/ /g; + } elsif ($escape eq 'latex') { # just do nbsp's here + $string =~ s/ +/~/g; + } + } + + $string; +} + =back =head1 BUGS