sub cust_status {
my $self = shift;
return $self->cust_unlinked_msg unless $self->cust_linked;
-
- #FS::cust_main::status($self)
- #false laziness w/actual cust_main::status
- # (make sure FS::cust_main methods are called)
- for my $status (qw( prospect active inactive suspended cancelled )) {
- my $method = $status.'_sql';
- my $sql = FS::cust_main->$method();;
- my $numnum = ( $sql =~ s/cust_main\.custnum/?/g );
- my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr;
- $sth->execute( ($self->custnum) x $numnum )
- or die "Error executing 'SELECT $sql': ". $sth->errstr;
- return $status if $sth->fetchrow_arrayref->[0];
- }
+ my $cust_main = $self->cust_main;
+ return $self->cust_unlinked_msg unless $cust_main;
+ return $cust_main->cust_status;
}
=item ucfirst_cust_status
: '000000';
}
+=item agent_name
+
+=cut
+
+sub agent_name {
+ my $self = shift;
+ $self->cust_linked
+ ? $self->cust_main->agent_name
+ : $self->cust_unlinked_msg;
+}
+
=item prospect_sql
=item active_sql
Text body
+=item to_contact_classnum
+
+The customer contact class (or classes, as a comma-separated list) to send
+the message to. If unspecified, will be sent to any contacts that are marked
+as invoice destinations (the equivalent of specifying 'invoice').
+
=back
Returns an error message, or false for success.
sub email_search_result {
my($class, $param) = @_;
+ my $conf = FS::Conf->new;
+ my $send_to_domain = $conf->config('email-to-voice_domain');
+
my $msgnum = $param->{msgnum};
my $from = delete $param->{from};
my $subject = delete $param->{subject};
my $html_body = delete $param->{html_body};
my $text_body = delete $param->{text_body};
+ my $to_contact_classnum = delete $param->{to_contact_classnum};
+ my $emailtovoice_name = delete $param->{emailtovoice_contact};
+
my $error = '';
+ my $to = $emailtovoice_name . '@' . $send_to_domain unless !$emailtovoice_name;
+
my $job = delete $param->{'job'}
or die "email_search_result must run from the job queue.\n";
next; # unlinked object; nothing else we can do
}
+ my %to = {};
+ if ($to) { $to{'to'} = $to; }
+
if ( $msg_template ) {
# Now supports other context objects.
%message = $msg_template->prepare(
'cust_main' => $cust_main,
'object' => $obj,
+ 'to_contact_classnum' => $to_contact_classnum,
+ %to
);
- }
- else {
- my @to = $cust_main->invoicing_list_emailonly;
+
+ } else {
+ # 3.x: false laziness with msg_template.pm; on 4.x, all email notices
+ # are generated from templates and this case goes away
+ my @classes;
+ if ( $to_contact_classnum ) {
+ @classes = ref($to_contact_classnum) ? @$to_contact_classnum : split(',', $to_contact_classnum);
+ }
+ if (!@classes) {
+ @classes = ( 'invoice' );
+ }
+ my @to = $to ? split(',', $to) : $cust_main->contact_list_email(@classes);
next if !@to;
%message = (
} #if $msg_template
# For non-cust_main searches, we avoid duplicates based on message
- # body text.
+ # body text.
my $unique = $cust_main->custnum;
$unique .= sha1($message{'text_body'}) if $class ne 'FS::cust_main';
if( $sent_to{$unique} ) {
$string;
}
+=item unsuspend_balance
+
+If conf I<unsuspend_balance> is set and customer's current balance is
+beneath the set threshold, unsuspends customer packages.
+
+=cut
+
+sub unsuspend_balance {
+ my $self = shift;
+ my $cust_main = $self->cust_main;
+ my $conf = $self->conf;
+ my $setting = $conf->config('unsuspend_balance');
+ my $maxbalance;
+ if ($setting eq 'Zero') {
+ $maxbalance = 0;
+
+ # kind of a pain to load/check all cust_bill instead of just open ones,
+ # but if for some reason payment gets applied to later bills before
+ # earlier ones, we still want to consider the later ones as allowable balance
+ } elsif ($setting eq 'Latest invoice charges') {
+ my @cust_bill = $cust_main->cust_bill();
+ my $cust_bill = $cust_bill[-1]; #always want the most recent one
+ if ($cust_bill) {
+ $maxbalance = $cust_bill->charged || 0;
+ } else {
+ $maxbalance = 0;
+ }
+ } elsif ($setting eq 'Charges not past due') {
+ my $now = time;
+ $maxbalance = 0;
+ foreach my $cust_bill ($cust_main->cust_bill()) {
+ next unless $now <= ($cust_bill->due_date || $cust_bill->_date);
+ $maxbalance += $cust_bill->charged || 0;
+ }
+ } elsif (length($setting)) {
+ warn "Unrecognized unsuspend_balance setting $setting";
+ return;
+ } else {
+ return;
+ }
+ my $balance = $cust_main->balance || 0;
+ if ($balance <= $maxbalance) {
+ my @errors = $cust_main->unsuspend;
+ # side-fx with nested transactions? upstack rolls back?
+ warn "WARNING:Errors unsuspending customer ". $cust_main->custnum. ": ".
+ join(' / ', @errors)
+ if @errors;
+ }
+ return;
+}
+
=back
=head1 BUGS