summaryrefslogtreecommitdiff
path: root/FS/FS/part_event
diff options
context:
space:
mode:
authorcvs2git <cvs2git>2010-11-05 19:05:57 +0000
committercvs2git <cvs2git>2010-11-05 19:05:57 +0000
commitaaf8baf3662e16e9414de236a39f8801a8c41b01 (patch)
tree2cda603e4311b3e80f79b93d9bcce3a7c7c2d053 /FS/FS/part_event
parent995a145c931164347683071c95c6754379d36604 (diff)
parent9b2de4257b6a2877434008188e52b8ef71ff339d (diff)
This commit was manufactured by cvs2svn to create branch
'FREESIDE_2_1_BRANCH'.
Diffstat (limited to 'FS/FS/part_event')
-rw-r--r--FS/FS/part_event/Action/notice.pm2
-rw-r--r--FS/FS/part_event/Action/notice_to.pm55
-rw-r--r--FS/FS/part_event/Condition.pm22
-rw-r--r--FS/FS/part_event/Condition/balance_age.pm2
-rw-r--r--FS/FS/part_event/Condition/balance_credit_limit.pm32
-rw-r--r--FS/FS/part_event/Condition/cust_bill_past_due.pm41
-rw-r--r--FS/FS/part_event/Condition/cust_status.pm8
-rw-r--r--FS/FS/part_event/Condition/has_referral_custnum.pm10
-rw-r--r--FS/FS/part_event/Condition/once_every.pm46
-rw-r--r--FS/FS/part_event/Condition/once_perinv.pm57
-rw-r--r--FS/FS/part_event/Condition/payby.pm16
-rw-r--r--FS/FS/part_event/Condition/pkg_age.pm16
-rw-r--r--FS/FS/part_event/Condition/pkg_next_bill_within.pm51
-rw-r--r--FS/FS/part_event/Condition/pkg_recurring.pm9
-rw-r--r--FS/FS/part_event/Condition/pkg_status.pm7
15 files changed, 346 insertions, 28 deletions
diff --git a/FS/FS/part_event/Action/notice.pm b/FS/FS/part_event/Action/notice.pm
index 1269653..8e22c68 100644
--- a/FS/FS/part_event/Action/notice.pm
+++ b/FS/FS/part_event/Action/notice.pm
@@ -5,7 +5,7 @@ use base qw( FS::part_event::Action );
use FS::Record qw( qsearchs );
use FS::msg_template;
-sub description { 'Send a notice from a message template'; }
+sub description { 'Email a notice to the customer\'s billing address'; }
#sub eventtable_hashref {
# { 'cust_main' => 1,
diff --git a/FS/FS/part_event/Action/notice_to.pm b/FS/FS/part_event/Action/notice_to.pm
new file mode 100644
index 0000000..194aeb8
--- /dev/null
+++ b/FS/FS/part_event/Action/notice_to.pm
@@ -0,0 +1,55 @@
+package FS::part_event::Action::notice_to;
+
+use strict;
+use base qw( FS::part_event::Action );
+use FS::Record qw( qsearchs );
+use FS::msg_template;
+
+sub description { 'Email a notice to a specific address'; }
+
+#sub eventtable_hashref {
+# { 'cust_main' => 1,
+# 'cust_bill' => 1,
+# 'cust_pkg' => 1,
+# };
+#}
+
+sub option_fields {
+ (
+ 'to' => { 'label' => 'Destination',
+ 'type' => 'text',
+ 'size' => 30,
+ },
+ 'msgnum' => { 'label' => 'Template',
+ 'type' => 'select-table',
+ 'table' => 'msg_template',
+ 'name_col' => 'msgname',
+ 'disable_empty' => 1,
+ },
+ );
+}
+
+sub default_weight { 56; } #?
+
+sub do_action {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ my $msgnum = $self->option('msgnum');
+
+ my $msg_template = qsearchs('msg_template', { 'msgnum' => $msgnum } )
+ or die "Template $msgnum not found";
+
+ my $to = $self->option('to')
+ or die "Can't send notice without a destination address";
+
+ $msg_template->send(
+ 'to' => $to,
+ 'cust_main' => $cust_main,
+ 'object' => $object,
+ );
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition.pm b/FS/FS/part_event/Condition.pm
index ddd8a61..90b8385 100644
--- a/FS/FS/part_event/Condition.pm
+++ b/FS/FS/part_event/Condition.pm
@@ -306,6 +306,28 @@ sub condition_sql_option {
)";
}
+#c.f. part_event_condition_option.pm / part_event_condition_option_option
+#used for part_event/Condition/payby.pm
+sub condition_sql_option_option {
+ my( $class, $option ) = @_;
+
+ ( my $condname = $class ) =~ s/^.*:://;
+
+ my $optionnum =
+ "( SELECT optionnum FROM part_event_condition_option
+ WHERE part_event_condition_option.eventconditionnum =
+ cond_$condname.eventconditionnum
+ AND part_event_condition_option.optionname = '$option'
+ AND part_event_condition_option.optionvalue = 'HASH'
+ )";
+
+ "( SELECT optionname FROM part_event_condition_option_option
+ WHERE optionnum = $optionnum
+ )";
+
+}
+
+
=item condition_sql_option_age_from OPTION FROM_TIMESTAMP
This is a class method that returns an SQL fragment that will retreive a
diff --git a/FS/FS/part_event/Condition/balance_age.pm b/FS/FS/part_event/Condition/balance_age.pm
index fc34612..8480659 100644
--- a/FS/FS/part_event/Condition/balance_age.pm
+++ b/FS/FS/part_event/Condition/balance_age.pm
@@ -45,8 +45,6 @@ sub order_sql {
shift->condition_sql_option_age('age');
}
-use FS::UID qw( driver_name );
-
sub order_sql_weight {
10;
}
diff --git a/FS/FS/part_event/Condition/balance_credit_limit.pm b/FS/FS/part_event/Condition/balance_credit_limit.pm
new file mode 100644
index 0000000..1bc2aa1
--- /dev/null
+++ b/FS/FS/part_event/Condition/balance_credit_limit.pm
@@ -0,0 +1,32 @@
+package FS::part_event::Condition::balance_credit_limit;
+
+use strict;
+use FS::cust_main;
+
+use base qw( FS::part_event::Condition );
+
+sub description { 'Customer is over credit limit'; }
+
+sub condition {
+ my($self, $object) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ my $over = $cust_main->credit_limit;
+ return 0 if !length($over); # if credit limit is null, no limit
+
+ $cust_main->balance > $over;
+}
+
+sub condition_sql {
+ my( $class, $table ) = @_;
+
+ my $balance_sql = FS::cust_main->balance_sql;
+
+ "(cust_main.credit_limit IS NULL OR
+ $balance_sql - cust_main.credit_limit > 0 )";
+
+}
+
+1;
+
diff --git a/FS/FS/part_event/Condition/cust_bill_past_due.pm b/FS/FS/part_event/Condition/cust_bill_past_due.pm
new file mode 100644
index 0000000..a889a00
--- /dev/null
+++ b/FS/FS/part_event/Condition/cust_bill_past_due.pm
@@ -0,0 +1,41 @@
+package FS::part_event::Condition::cust_bill_past_due;
+
+use strict;
+use FS::cust_bill;
+use Time::Local 'timelocal';
+
+use base qw( FS::part_event::Condition );
+
+sub description {
+ 'Invoice due date has passed';
+}
+
+sub eventtable_hashref {
+ { 'cust_main' => 0,
+ 'cust_bill' => 1,
+ 'cust_pkg' => 0,
+ };
+}
+
+sub condition {
+ my($self, $cust_bill, %opt) = @_;
+
+ # If the invoice date is 1/1 at noon and the terms are Net 15,
+ # the due_date will be 1/16 at noon. Past due events will not
+ # trigger until after the start of 1/17.
+ my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($opt{'time'}))[0..5];
+ my $start_of_today = timelocal(0,0,0,$mday,$mon,$year)+1;
+ ($cust_bill->due_date || $cust_bill->_date) < $start_of_today;
+}
+
+sub condition_sql {
+ return 'true' if $FS::UID::driver_name ne 'Pg';
+ my( $class, $table, %opt ) = @_;
+ my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($opt{'time'}))[0..5];
+ my $start_of_today = timelocal(0,0,0,$mday,$mon,$year)+1;
+
+ FS::cust_bill->due_date_sql . " < $start_of_today";
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/cust_status.pm b/FS/FS/part_event/Condition/cust_status.pm
index fbdff25..066ee48 100644
--- a/FS/FS/part_event/Condition/cust_status.pm
+++ b/FS/FS/part_event/Condition/cust_status.pm
@@ -29,4 +29,12 @@ sub condition {
$hashref->{ $cust_main->status };
}
+sub condition_sql {
+ my( $self, $table ) = @_;
+
+ '('.FS::cust_main->cust_status_sql . ') IN '.
+ $self->condition_sql_option_option('status');
+}
+
+
1;
diff --git a/FS/FS/part_event/Condition/has_referral_custnum.pm b/FS/FS/part_event/Condition/has_referral_custnum.pm
index 61a8155..70c9c7f 100644
--- a/FS/FS/part_event/Condition/has_referral_custnum.pm
+++ b/FS/FS/part_event/Condition/has_referral_custnum.pm
@@ -38,11 +38,13 @@ sub condition {
}
sub condition_sql {
- #my( $class, $table ) = @_;
+ my( $class, $table ) = @_;
- "cust_main.referral_custnum IS NOT NULL";
-
- #XXX a bit harder to check active status here
+ my $sql = FS::cust_main->active_sql;
+ $sql =~ s/cust_main.custnum/cust_main.referral_custnum/;
+ $sql = 'cust_main.referral_custnum IS NOT NULL AND ('.
+ $class->condition_sql_option('active') . ' IS NULL OR '.$sql.')';
+ return $sql;
}
1;
diff --git a/FS/FS/part_event/Condition/once_every.pm b/FS/FS/part_event/Condition/once_every.pm
new file mode 100644
index 0000000..2921b3a
--- /dev/null
+++ b/FS/FS/part_event/Condition/once_every.pm
@@ -0,0 +1,46 @@
+package FS::part_event::Condition::once_every;
+
+use strict;
+use FS::Record qw( qsearch );
+use FS::part_event;
+use FS::cust_event;
+
+use base qw( FS::part_event::Condition );
+
+sub description { "Don't run this event more than once in the specified interval"; }
+
+# Runs the event at most "once every X".
+
+sub option_fields {
+ (
+ 'run_delay' => { label=>'Interval', type=>'freq', value=>'1m', },
+ );
+}
+
+sub condition {
+ my($self, $object, %opt) = @_;
+
+ my $obj_pkey = $object->primary_key;
+ my $tablenum = $object->$obj_pkey();
+
+ my $max_date = $self->option_age_from('run_delay',$opt{'time'});
+
+ my @existing = qsearch( {
+ 'table' => 'cust_event',
+ 'hashref' => {
+ 'eventpart' => $self->eventpart,
+ 'tablenum' => $tablenum,
+ 'status' => { op=>'!=', value=>'failed' },
+ '_date' => { op=>'>=', value=>$max_date },
+ },
+ 'extra_sql' => ( $opt{'cust_event'}->eventnum =~ /^(\d+)$/
+ ? " AND eventnum != $1 "
+ : ''
+ ),
+ } );
+
+ ! scalar(@existing);
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/once_perinv.pm b/FS/FS/part_event/Condition/once_perinv.pm
new file mode 100644
index 0000000..f85a056
--- /dev/null
+++ b/FS/FS/part_event/Condition/once_perinv.pm
@@ -0,0 +1,57 @@
+package FS::part_event::Condition::once_perinv;
+
+use strict;
+use FS::Record qw( qsearch );
+use FS::part_event;
+use FS::cust_event;
+
+use base qw( FS::part_event::Condition );
+
+sub description { "Run only once for each time the package has been billed"; }
+
+# Run the event, at most, a number of times equal to the number of
+# distinct invoices that contain line items from this package.
+
+sub eventtable_hashref {
+ { 'cust_main' => 0,
+ 'cust_bill' => 0,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub condition {
+ my($self, $cust_pkg, %opt) = @_;
+
+ my %invnum;
+ $invnum{$_->invnum} = 1
+ foreach ( qsearch('cust_bill_pkg', { 'pkgnum' => $cust_pkg->pkgnum }) );
+ my @events = qsearch( {
+ 'table' => 'cust_event',
+ 'hashref' => { 'eventpart' => $self->eventpart,
+ 'status' => { op=>'!=', value=>'failed' },
+ 'tablenum' => $cust_pkg->pkgnum,
+ },
+ 'extra_sql' => ( $opt{'cust_event'}->eventnum =~ /^(\d+)$/
+ ? " AND eventnum != $1 " : '' ),
+ } );
+ scalar(@events) < scalar(keys %invnum);
+}
+
+sub condition_sql {
+ my( $self, $table ) = @_;
+
+ "(
+ ( SELECT COUNT(distinct(invnum))
+ FROM cust_bill_pkg
+ WHERE cust_bill_pkg.pkgnum = cust_pkg.pkgnum )
+ >
+ ( SELECT COUNT(*)
+ FROM cust_event
+ WHERE cust_event.eventpart = part_event.eventpart
+ AND cust_event.tablenum = cust_pkg.pkgnum
+ AND status != 'failed' )
+ )"
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/payby.pm b/FS/FS/part_event/Condition/payby.pm
index d931568..16bf480 100644
--- a/FS/FS/part_event/Condition/payby.pm
+++ b/FS/FS/part_event/Condition/payby.pm
@@ -30,21 +30,15 @@ sub condition {
my $cust_main = $self->cust_main($object);
- #uuh.. all right? test this.
my $hashref = $self->option('payby') || {};
$hashref->{ $cust_main->payby };
}
-#sub condition_sql {
-# my( $self, $table ) = @_;
-#
-# #uuh... yeah... something like this. test it for sure.
-#
-# my @payby = keys %{ $self->option('payby') };
-#
-# ' ( '. join(' OR ', map { "cust_main.payby = '$_'" } @payby ). ' ) ';
-#
-#}
+sub condition_sql {
+ my( $self, $table ) = @_;
+
+ 'cust_main.payby IN '. $self->condition_sql_option_option('payby');
+}
1;
diff --git a/FS/FS/part_event/Condition/pkg_age.pm b/FS/FS/part_event/Condition/pkg_age.pm
index 8b3b4c9..4a85387 100644
--- a/FS/FS/part_event/Condition/pkg_age.pm
+++ b/FS/FS/part_event/Condition/pkg_age.pm
@@ -49,10 +49,18 @@ sub condition {
}
-#XXX write me for efficiency
-#sub condition_sql {
-#
-#}
+sub condition_sql {
+ my( $class, $table, %opt ) = @_;
+ my $age = $class->condition_sql_option_age_from('age', $opt{'time'});
+ my $field = $class->condition_sql_option('field');
+#amazingly, this is actually faster
+ my $sql = '( CASE';
+ foreach( qw(setup last_bill bill adjourn susp expire cancel) ) {
+ $sql .= " WHEN $field = '$_' THEN (cust_pkg.$_ IS NOT NULL AND cust_pkg.$_ <= $age)";
+ }
+ $sql .= ' END )';
+ return $sql;
+}
1;
diff --git a/FS/FS/part_event/Condition/pkg_next_bill_within.pm b/FS/FS/part_event/Condition/pkg_next_bill_within.pm
new file mode 100644
index 0000000..90c4c6a
--- /dev/null
+++ b/FS/FS/part_event/Condition/pkg_next_bill_within.pm
@@ -0,0 +1,51 @@
+package FS::part_event::Condition::pkg_next_bill_within;
+
+use strict;
+use base qw( FS::part_event::Condition );
+use FS::Record qw( qsearch );
+
+sub description {
+ 'Next bill date within upcoming interval';
+}
+
+# Run the event when the next bill date is within X days.
+# To clarify, that's within X days _after_ the current date,
+# not before.
+# Combine this with a "once_every" condition so that the event
+# won't repeat every day until the bill date.
+
+sub eventtable_hashref {
+ { 'cust_main' => 0,
+ 'cust_bill' => 0,
+ 'cust_pkg' => 1,
+ };
+}
+
+sub option_fields {
+ (
+ 'within' => { 'label' => 'Bill date within',
+ 'type' => 'freq',
+ },
+ # possibly "field" to allow date fields besides 'bill'?
+ );
+}
+
+sub condition {
+ my( $self, $cust_pkg, %opt ) = @_;
+
+ my $pkg_date = $cust_pkg->get('bill') or return 0;
+ $pkg_date = $self->option_age_from('within', $pkg_date );
+
+ $opt{'time'} >= $pkg_date;
+
+}
+
+#XXX write me for efficiency
+sub condition_sql {
+ my ($self, $table, %opt) = @_;
+ $opt{'time'}.' >= '.
+ $self->condition_sql_option_age_from('within', 'cust_pkg.bill')
+}
+
+1;
+
diff --git a/FS/FS/part_event/Condition/pkg_recurring.pm b/FS/FS/part_event/Condition/pkg_recurring.pm
index 1b66821..1a08869 100644
--- a/FS/FS/part_event/Condition/pkg_recurring.pm
+++ b/FS/FS/part_event/Condition/pkg_recurring.pm
@@ -20,12 +20,9 @@ sub condition {
}
-
-#XXX join part_pkg USING (pkgpart)
-# part_pkg.freq != '0'
-#sub condition_sql {
-#
-#}
+sub condition_sql {
+ FS::cust_pkg->recurring_sql()
+}
1;
diff --git a/FS/FS/part_event/Condition/pkg_status.pm b/FS/FS/part_event/Condition/pkg_status.pm
index 6c1c9cc..3fb374e 100644
--- a/FS/FS/part_event/Condition/pkg_status.pm
+++ b/FS/FS/part_event/Condition/pkg_status.pm
@@ -34,4 +34,11 @@ sub condition {
$hashref->{ $cust_pkg->status };
}
+sub condition_sql {
+ my( $self, $table ) = @_;
+
+ '('.FS::cust_pkg->status_sql . ') IN '.
+ $self->condition_sql_option_option('status');
+}
+
1;