package FS::cust_event;
use strict;
-use vars qw( @ISA $DEBUG );
+use base qw( FS::cust_main_Mixin FS::Record );
+use vars qw( @ISA $DEBUG $me );
use Carp qw( croak confess );
use FS::Record qw( qsearch qsearchs dbdef );
-use FS::cust_main_Mixin;
use FS::part_event;
#for cust_X
use FS::cust_main;
use FS::cust_pkg;
use FS::cust_bill;
-
-@ISA = qw(FS::cust_main_Mixin FS::Record);
+use FS::svc_acct;
$DEBUG = 0;
+$me = '[FS::cust_event]';
=head1 NAME
$dbdef_eventtable->primary_key
)
|| $self->ut_number('_date')
- || $self->ut_enum('status', [qw( new locked done failed )])
+ || $self->ut_enum('status', [qw( new locked done failed initial)])
|| $self->ut_anything('statustext')
;
return $error if $error;
my $object = $self->cust_X;
my @conditions = $part_event->part_event_condition;
$opt{'cust_event'} = $self;
+ $opt{'time'} = $self->_date
+ or die "test_conditions called without cust_event._date\n";
+ # this MUST be set, or all hell breaks loose in event conditions.
+ # it MUST be in the same time as in the cust_event object, or
+ # future time-dependent events will trigger incorrectly.
#no unsatisfied conditions
#! grep ! $_->condition( $object, %opt ), @conditions;
sub do_event {
my $self = shift;
+ my %opt = @_; # currently only 'time'
+ my $time = $opt{'time'} || time;
my $part_event = $self->part_event;
" (". $part_event->action. ") $for\n"
if $DEBUG;
- my $oldAutoCommit = $FS::UID::AutoCommit;
- local $FS::UID::AutoCommit = 0;
-
my $error;
{
local $SIG{__DIE__}; # don't want Mason __DIE__ handler active
- $error = eval { $part_event->do_action($object); };
+ $error = eval { $part_event->do_action($object, $self); };
}
my $status = '';
}
#replace or add myself
- $self->_date(time);
+ $self->_date($time);
$self->status($status);
$self->statustext($statustext);
$self->replace($old);
}
+=item join_sql
+
+=cut
+
+sub join_sql {
+ #my $class = shift;
+
+ "
+ JOIN part_event USING ( eventpart )
+ LEFT JOIN cust_bill ON ( eventtable = 'cust_bill' AND tablenum = invnum )
+ LEFT JOIN cust_pkg ON ( eventtable = 'cust_pkg' AND tablenum = pkgnum )
+
+ LEFT JOIN cust_svc ON ( eventtable = 'svc_acct' AND tablenum = svcnum )
+ LEFT JOIN cust_pkg AS cust_pkg_for_svc ON ( cust_svc.pkgnum = cust_pkg_for_svc.pkgnum )
+ LEFT JOIN cust_main ON ( ( eventtable = 'cust_main' AND tablenum = cust_main.custnum )
+ OR ( eventtable = 'cust_bill' AND cust_bill.custnum = cust_main.custnum )
+ OR ( eventtable = 'cust_pkg' AND cust_pkg.custnum = cust_main.custnum )
+ OR ( eventtable = 'svc_acct' AND cust_pkg_for_svc.custnum = cust_main.custnum )
+ )
+ ";
+
+}
+
+=item search_sql_where HASHREF
+
+Class method which returns an SQL WHERE fragment to search for parameters
+specified in HASHREF. Valid parameters are
+
+=over 4
+
+=item agentnum
+
+=item custnum
+
+=item invnum
+
+=item pkgnum
+
+=item svcnum
+
+=item failed
+
+=item beginning
+
+=item ending
+
+=item payby
+
+=item
+
+=back
+
+=cut
+
+#Note: validates all passed-in data; i.e. safe to use with unchecked CGI params.
+#sub
+
+sub search_sql_where {
+ my($class, $param) = @_;
+ if ( $DEBUG ) {
+ warn "$me search_sql_where called with params: \n".
+ join("\n", map { " $_: ". $param->{$_} } keys %$param ). "\n";
+ }
+
+ my @search = $class->cust_search_sql($param);
+
+ #eventpart
+ my @eventpart = ref($param->{'eventpart'})
+ ? @{ $param->{'eventpart'} }
+ : split(',', $param->{'eventpart'});
+ @eventpart = grep /^(\d+)$/, @eventpart;
+ if ( @eventpart ) {
+ push @search, 'eventpart IN ('. join(',', @eventpart). ')';
+ }
+
+ if ( $param->{'beginning'} =~ /^(\d+)$/ ) {
+ push @search, "cust_event._date >= $1";
+ }
+ if ( $param->{'ending'} =~ /^(\d+)$/ ) {
+ push @search, "cust_event._date <= $1";
+ }
+
+ if ( $param->{'failed'} ) {
+ push @search, "statustext != ''",
+ "statustext IS NOT NULL",
+ "statustext != 'N/A'";
+ }
+
+ if ( $param->{'custnum'} =~ /^(\d+)$/ ) {
+ push @search, "cust_main.custnum = '$1'";
+ }
+
+ if ( $param->{'invnum'} =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_bill'",
+ "tablenum = '$1'";
+ }
+
+ if ( $param->{'pkgnum'} =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'cust_pkg'",
+ "tablenum = '$1'";
+ }
+
+ if ( $param->{'svcnum'} =~ /^(\d+)$/ ) {
+ push @search, "part_event.eventtable = 'svc_acct'",
+ "tablenum = '$1'";
+ }
+
+ my $where = 'WHERE '. join(' AND ', @search );
+
+ join(' AND ', @search );
+
+}
+
=back
=head1 SUBROUTINES
re_X(
$method,
- $param->{'beginning'},
- $param->{'ending'},
- $param->{'failed'},
+ $param,
$job,
);
}
-#this needs some updating based on the 1.7 cust_bill_event.pm still, i think
sub re_X {
- my($method, $beginning, $ending, $failed, $job) = @_;
+ my($method, $param, $job) = @_;
+
+ my $search_sql = FS::cust_event->search_sql_where($param);
- my $from = 'LEFT JOIN part_event USING ( eventpart )';
+ #maybe not...? we do want the "re-" action to match the search more closely
+ # # yuck! hardcoded *AND* sequential scans!
+ #my $where = " WHERE action LIKE 'cust_bill_send%' ".
+ # ( $search_sql ? " AND $search_sql" : "" );
- # yuck! hardcoded *AND* sequential scans!
- my $where = " WHERE action LIKE 'cust_bill_send%'".
- " AND cust_event._date >= $beginning".
- " AND cust_event._date <= $ending";
- $where .= " AND statustext != '' AND statustext IS NOT NULL"
- if $failed;
+ my $where = ( $search_sql ? " WHERE $search_sql" : "" );
my @cust_event = qsearch({
'table' => 'cust_event',
- 'addl_from' => $from,
+ 'addl_from' => FS::cust_event->join_sql(),
'hashref' => {},
'extra_sql' => $where,
});
+ warn "$me re_X found ". scalar(@cust_event). " events\n"
+ if $DEBUG;
+
my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
foreach my $cust_event ( @cust_event ) {
- $cust_event->cust_X->$method(
- $cust_event->part_event->templatename
- || $cust_event->cust_X->agent_template
- );
+ my $cust_X = $cust_event->cust_X; # cust_bill
+ next unless $cust_X->can($method);
+
+ $cust_X->$method( $cust_event->part_event->templatename
+ || $cust_X->agent_template
+ );
if ( $job ) { #progressbar foo
$num++;