From a6aa711eb82626bfab39902a6c4d785f3f533ef4 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 6 Mar 2002 22:44:14 +0000 Subject: billing expiration alerts --- FS/bin/freeside-expiration-alerter | 209 +++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100755 FS/bin/freeside-expiration-alerter (limited to 'FS/bin/freeside-expiration-alerter') diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter new file mode 100755 index 000000000..c3dc37b31 --- /dev/null +++ b/FS/bin/freeside-expiration-alerter @@ -0,0 +1,209 @@ +#!/usr/bin/perl -Tw + +use strict; +use Date::Format; +use Time::Local; +use Text::Template; +use Getopt::Std; +use FS::Conf; +use FS::UID qw(adminsuidsetup); +use FS::Record qw(qsearch); +use FS::cust_main; + +use vars qw($smtpmachine); + +#hush, perl! +$FS::alerter::_template::first = ""; +$FS::alerter::_template::last = ""; +$FS::alerter::_template::company = ""; +$FS::alerter::_template::payby = ""; +$FS::alerter::_template::expdate = ""; + +# Set the mail program and other variables +my $mail_program = "/usr/sbin/sendmail -t -n"; +my $mail_sender = "billing\@mydomain.tld"; +my $default_mail_recipient = "postmaster"; +my $warning_time = 30 * 24 * 60 * 60; +my $urgent_time = 15 * 24 * 60 * 60; +my $panic_time = 5 * 24 * 60 * 60; +my $window_time = 24 * 60 * 60; + +&untaint_argv; #what it sounds like (eww) + +#we're at now now (and later). +my($_date)= $^T; + +# Get the current month +my ($sec,$min,$hour,$mday,$mon,$year) = + (localtime($_date) )[0,1,2,3,4,5]; +$mon++; + +# Login to the database +my $user = shift or die &usage; +adminsuidsetup $user; + +# Get the needed configuration files +my $conf = new FS::Conf; +$smtpmachine = $conf->config('smtpmachine'); + +my(@customers)=qsearch('cust_main',{}); +if (scalar(@customers) == 0) +{ + exit 1; +} + +# Open email pipe + +open (MAIL, "|$mail_program"); +print MAIL <config('alerter_template') + or die "cannot load config file alerter_template"; + +my $alerter = new Text::Template (TYPE => 'ARRAY', SOURCE => [ map "$_\n", @alerter_template ]) + or die "can't create new Text::Template object: Text::Template::ERROR"; +$alerter->compile() or die "can't compile template: Text::Template::ERROR"; + +# Now I can start looping +foreach my $customer (@customers) +{ + my $custnum = $customer->getfield('custnum'); + my $first = $customer->getfield('first'); + my $last = $customer->getfield('last'); + my $company = $customer->getfield('company'); + my $payby = $customer->getfield('payby'); + my $payinfo = $customer->getfield('payinfo'); + my $paydate = $customer->getfield('paydate'); + my $daytime = $customer->getfield('daytime'); + my $night = $customer->getfield('night'); + + my ($payyear,$paymonth,$payday) = split (/-/,$paydate); + + my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear); + + #credit cards expire at the end of the month/year of their exp date + if ($payby eq 'CARD') { + ($paymonth < 11) ? $paymonth++ : ($paymonth=0, $payyear++); + $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear); + $expire_time--; + } + + if (($expire_time < $_date + $warning_time && + $expire_time > $_date + $warning_time - $window_time) || + ($expire_time < $_date + $urgent_time && + $expire_time > $_date + $urgent_time - $window_time) || + ($expire_time < $_date + $panic_time && + $expire_time > $_date + $panic_time - $window_time)) { + + + + my @packages = $customer->ncancelled_pkgs; + if (scalar(@packages) != 0) { + my @invoicing_list = $customer->invoicing_list; + if ( grep { $_ ne 'POST' } @invoicing_list ) { + $ENV{SMTPHOSTS} = $smtpmachine; + $ENV{MAILADDRESS} = $mail_sender; + my $header = new Mail::Header ( [ + "From: $mail_sender", + "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), + "Sender: $mail_sender", + "Reply-To: $mail_sender", + "Date: ". time2str("%a, %d %b %Y %X %z", time), + "Subject: Billing Arrangement Expiration", + ] ); + $FS::alerter::_template::first = $first; + $FS::alerter::_template::last = $last; + $FS::alerter::_template::company = $company; + if ($payby eq 'CARD') { + $FS::alerter::_template::payby = "credit card (" . + substr($payinfo, 0, 2) . "xxxxxxxxxx" . + substr($payinfo, -4) . ")"; + }elsif ($payby eq 'COMP') { + $FS::alerter::_template::payby = "complimentary account"; + }else{ + $FS::alerter::_template::payby = "current method"; + } + $FS::alerter::_template::expdate = $expire_time; + + my $message = new Mail::Internet ( + 'Header' => $header, + 'Body' => [ $alerter->fill_in( PACKAGE => 'FS::alerter::_template' ) ], + ); + $message->smtpsend or die "Can't send invoice email!: $!"; #die? warn? + + } elsif ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) { + printf(MAIL qq{%5d %-32.32s %4s %10s %12s %12s\n}, + $custnum, + $first . " " . $last . " " . $company, + $payby, + $paydate, + $daytime, + $night); + } + } + } +} + +# Now I need to close EMAIL +close MAIL || die "Could not close printer: $default_mail_recipient\n"; + + +# subroutines +sub untaint_argv { + foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV + $ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal argument \"$ARGV[$_]\""; + $ARGV[$_]=$1; + } +} + +sub usage { + die "Usage:\n\n freeside-expiration-alerter user\n"; +} + +=head1 NAME + +freeside-expiration-alerter - Emails notifications of credit card expirations. + +=head1 SYNOPSIS + + freeside-expiration-alerter user + +=head1 DESCRIPTION + +Emails customers notice that their credit card or other billing arrangement +is about to expire. Usually run as a cron job. + +user: From the mapsecrets file - see config.html from the base documentation + +=head1 VERSION + +$Id: freeside-expiration-alerter,v 1.1 2002-03-06 22:44:13 jeff Exp $ + +=head1 BUGS + +Yes..... Use at your own risk. No guarantees or warrantees of any +kind apply to this program. Parts of this program are hacked from +other GNU licensed software created mainly by Ivan Kohler. + +This is released under the GNU Public License. See www.gnu.org +for more information regarding this license. + +=head1 SEE ALSO + +L, config.html from the base documentation + +=head1 AUTHOR + +Jeff Finucane + +=cut + + -- cgit v1.2.1 From 3e2e5fecb9ef3cf39a6ac098aacb76763edd3938 Mon Sep 17 00:00:00 2001 From: jeff Date: Thu, 7 Mar 2002 19:50:24 +0000 Subject: less shelling, more perly - abolish some pipes to sendmail --- FS/bin/freeside-expiration-alerter | 60 +++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'FS/bin/freeside-expiration-alerter') diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter index c3dc37b31..365b96467 100755 --- a/FS/bin/freeside-expiration-alerter +++ b/FS/bin/freeside-expiration-alerter @@ -5,12 +5,15 @@ use Date::Format; use Time::Local; use Text::Template; use Getopt::Std; +use Net::SMTP; +use Mail::Header; +use Mail::Internet; use FS::Conf; use FS::UID qw(adminsuidsetup); use FS::Record qw(qsearch); use FS::cust_main; -use vars qw($smtpmachine); +use vars qw($smtpmachine @body); #hush, perl! $FS::alerter::_template::first = ""; @@ -20,9 +23,8 @@ $FS::alerter::_template::payby = ""; $FS::alerter::_template::expdate = ""; # Set the mail program and other variables -my $mail_program = "/usr/sbin/sendmail -t -n"; -my $mail_sender = "billing\@mydomain.tld"; -my $default_mail_recipient = "postmaster"; +my $mail_sender = "billing\@mydomain.tld"; # or invoice_from if available +my $failure_recipient = "postmaster"; # or invoice_from if available my $warning_time = 30 * 24 * 60 * 60; my $urgent_time = 15 * 24 * 60 * 60; my $panic_time = 5 * 24 * 60 * 60; @@ -45,6 +47,11 @@ adminsuidsetup $user; # Get the needed configuration files my $conf = new FS::Conf; $smtpmachine = $conf->config('smtpmachine'); +$mail_sender = $conf->config('invoice_from') + if $conf->exists('invoice_from'); +$failure_recipient = $conf->config('invoice_from') + if $conf->exists('invoice_from'); + my(@customers)=qsearch('cust_main',{}); if (scalar(@customers) == 0) @@ -52,18 +59,16 @@ if (scalar(@customers) == 0) exit 1; } -# Open email pipe - -open (MAIL, "|$mail_program"); -print MAIL <config('alerter_template') or die "cannot load config file alerter_template"; @@ -109,8 +114,6 @@ foreach my $customer (@customers) if (scalar(@packages) != 0) { my @invoicing_list = $customer->invoicing_list; if ( grep { $_ ne 'POST' } @invoicing_list ) { - $ENV{SMTPHOSTS} = $smtpmachine; - $ENV{MAILADDRESS} = $mail_sender; my $header = new Mail::Header ( [ "From: $mail_sender", "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), @@ -137,10 +140,12 @@ foreach my $customer (@customers) 'Header' => $header, 'Body' => [ $alerter->fill_in( PACKAGE => 'FS::alerter::_template' ) ], ); - $message->smtpsend or die "Can't send invoice email!: $!"; #die? warn? + $!=0; + $message->smtpsend( Host => $smtpmachine ) + or die "Can't send expiration email!: $!"; #die? warn? } elsif ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) { - printf(MAIL qq{%5d %-32.32s %4s %10s %12s %12s\n}, + push @body, sprintf(qq{%5d %-32.32s %4s %10s %12s %12s}, $custnum, $first . " " . $last . " " . $company, $payby, @@ -152,9 +157,18 @@ foreach my $customer (@customers) } } -# Now I need to close EMAIL -close MAIL || die "Could not close printer: $default_mail_recipient\n"; - +# Now I need to send EMAIL +if (scalar(@body)) { + my $message = new Mail::Internet ( + 'Header' => $header, + 'Body' => [ (@body) ], + ); + $!=0; + $message->smtpsend( Host => $smtpmachine ) + or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) + or return "can't send alerter failure email to $failure_recipient". + " via server $smtpmachine with SMTP: $!"; +} # subroutines sub untaint_argv { @@ -185,7 +199,7 @@ user: From the mapsecrets file - see config.html from the base documentation =head1 VERSION -$Id: freeside-expiration-alerter,v 1.1 2002-03-06 22:44:13 jeff Exp $ +$Id: freeside-expiration-alerter,v 1.2 2002-03-07 19:50:24 jeff Exp $ =head1 BUGS -- cgit v1.2.1 From 17ddcceb66e4c5c45abe890403d2ca98b128d375 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 16 Apr 2002 09:38:20 +0000 Subject: - send a notice to the customer when their card is declined - closes: Bug#351 - freeside-expiration-alerter works fine, closes: Bug#7 --- FS/bin/freeside-expiration-alerter | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'FS/bin/freeside-expiration-alerter') diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter index 365b96467..ee3c1fb92 100755 --- a/FS/bin/freeside-expiration-alerter +++ b/FS/bin/freeside-expiration-alerter @@ -142,7 +142,8 @@ foreach my $customer (@customers) ); $!=0; $message->smtpsend( Host => $smtpmachine ) - or die "Can't send expiration email!: $!"; #die? warn? + or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) + or die "Can't send expiration email: $!"; } elsif ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) { push @body, sprintf(qq{%5d %-32.32s %4s %10s %12s %12s}, @@ -166,8 +167,8 @@ if (scalar(@body)) { $!=0; $message->smtpsend( Host => $smtpmachine ) or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or return "can't send alerter failure email to $failure_recipient". - " via server $smtpmachine with SMTP: $!"; + or die "can't send alerter failure email to $failure_recipient". + " via server $smtpmachine with SMTP: $!"; } # subroutines @@ -199,7 +200,7 @@ user: From the mapsecrets file - see config.html from the base documentation =head1 VERSION -$Id: freeside-expiration-alerter,v 1.2 2002-03-07 19:50:24 jeff Exp $ +$Id: freeside-expiration-alerter,v 1.3 2002-04-16 09:38:19 ivan Exp $ =head1 BUGS -- cgit v1.2.1 From 3548c2951a51ece84687e3bfb5e435008191a713 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 16 Sep 2002 09:27:14 +0000 Subject: skip empty expiration dates --- FS/bin/freeside-expiration-alerter | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'FS/bin/freeside-expiration-alerter') diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter index ee3c1fb92..5399f6d22 100755 --- a/FS/bin/freeside-expiration-alerter +++ b/FS/bin/freeside-expiration-alerter @@ -80,16 +80,18 @@ $alerter->compile() or die "can't compile template: Text::Template::ERROR"; # Now I can start looping foreach my $customer (@customers) { + my $paydate = $customer->getfield('paydate'); + next if $paydate =~ /^\s*$/; #skip empty expiration dates + my $custnum = $customer->getfield('custnum'); my $first = $customer->getfield('first'); my $last = $customer->getfield('last'); my $company = $customer->getfield('company'); my $payby = $customer->getfield('payby'); my $payinfo = $customer->getfield('payinfo'); - my $paydate = $customer->getfield('paydate'); my $daytime = $customer->getfield('daytime'); my $night = $customer->getfield('night'); - + my ($payyear,$paymonth,$payday) = split (/-/,$paydate); my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear); @@ -200,7 +202,7 @@ user: From the mapsecrets file - see config.html from the base documentation =head1 VERSION -$Id: freeside-expiration-alerter,v 1.3 2002-04-16 09:38:19 ivan Exp $ +$Id: freeside-expiration-alerter,v 1.4 2002-09-16 09:27:14 ivan Exp $ =head1 BUGS -- cgit v1.2.1 From 030bef17868168b05a67d9f5866b55da1bb9439c Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 21 Apr 2003 20:53:57 +0000 Subject: on-demand vs. automatic cards & checks: added DCRD and DCHK payment types --- FS/bin/freeside-expiration-alerter | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'FS/bin/freeside-expiration-alerter') diff --git a/FS/bin/freeside-expiration-alerter b/FS/bin/freeside-expiration-alerter index 5399f6d22..691fd3aa5 100755 --- a/FS/bin/freeside-expiration-alerter +++ b/FS/bin/freeside-expiration-alerter @@ -97,7 +97,7 @@ foreach my $customer (@customers) my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear); #credit cards expire at the end of the month/year of their exp date - if ($payby eq 'CARD') { + if ($payby eq 'CARD' || $payby eq 'DCRD') { ($paymonth < 11) ? $paymonth++ : ($paymonth=0, $payyear++); $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear); $expire_time--; @@ -127,7 +127,7 @@ foreach my $customer (@customers) $FS::alerter::_template::first = $first; $FS::alerter::_template::last = $last; $FS::alerter::_template::company = $company; - if ($payby eq 'CARD') { + if ($payby eq 'CARD' || $payby eq 'DCRD') { $FS::alerter::_template::payby = "credit card (" . substr($payinfo, 0, 2) . "xxxxxxxxxx" . substr($payinfo, -4) . ")"; @@ -202,7 +202,7 @@ user: From the mapsecrets file - see config.html from the base documentation =head1 VERSION -$Id: freeside-expiration-alerter,v 1.4 2002-09-16 09:27:14 ivan Exp $ +$Id: freeside-expiration-alerter,v 1.5 2003-04-21 20:53:57 ivan Exp $ =head1 BUGS -- cgit v1.2.1