1 package FS::part_event::Condition;
4 use base qw( FS::part_event_condition );
6 use FS::UID qw( driver_name );
10 FS::part_event::Condition - Base class for event conditions
14 package FS::part_event::Condition::mycondition;
16 use base FS::part_event::Condition;
20 FS::part_event::Condition is a base class for event conditions classes.
24 These methods are implemented in each condition class.
30 Condition classes must define a description method. This method should return
31 a scalar description of the condition.
33 =item eventtable_hashref
35 Condition classes must define an eventtable_hashref method if they can only be
36 tested against some kinds of tables. This method should return a hash reference
37 of eventtables (values set true indicate the condition can be tested):
39 sub eventtable_hashref {
43 'cust_pay_batch' => 0,
50 sub eventtable_hashref {
54 'cust_pay_batch' => 1,
60 Condition classes may define an option_fields method to indicate that they
61 accept one or more options.
63 This method should return a list of option names and option descriptions.
64 Each option description can be a scalar description, for simple options, or a
65 hashref with the following values:
69 =item label - Description
71 =item type - Currently text, money, checkbox, checkbox-multiple, select, select-agent, select-pkg_class, select-part_referral, select-table, fixed, hidden, (others can be implemented as httemplate/elements/tr-TYPE.html mason components). Defaults to text.
73 =item options - For checkbox-multiple and select, a list reference of available option values.
75 =item option_labels - For checkbox-multiple (and select?), a hash reference of availble option values and labels.
77 =item value - for checkbox, fixed, hidden (also a default for text, money, more?)
79 =item table - for select-table
81 =item name_col - for select-table
83 =item NOTE: See httemplate/elements/select-table.html for a full list of the optinal options for the select-table type
87 NOTE: A database connection is B<not> yet available when this subroutine is
94 'field' => 'description',
96 'another_field' => { 'label'=>'Amount', 'type'=>'money', },
98 'third_field' => { 'label' => 'Types',
99 'type' => 'checkbox-multiple',
100 'options' => [ 'h', 's' ],
101 'option_labels' => { 'h' => 'Happy',
114 =item condition CUSTOMER_EVENT_OBJECT
116 Condition classes must define a condition method. This method is evaluated
117 to determine if the condition has been met. The object which triggered the
118 event (an FS::cust_main, FS::cust_bill or FS::cust_pkg object) is passed as
119 the first argument. Additional arguments are list of key-value pairs.
121 To retreive option values, call the option method on the desired option, i.e.:
123 my( $self, $cust_object, %opts ) = @_;
124 $value_of_field = $self->option('field');
126 Available additional arguments:
128 $time = $opt{'time'}; #use this instead of time or $^T
130 $cust_event = $opt{'cust_event'}; #to retreive the cust_event object being tested
132 Return a true value if the condition has been met, and a false value if it has
135 =item condition_sql EVENTTABLE
137 Condition classes may optionally define a condition_sql method. This B<class>
138 method should return an SQL fragment that tests for this condition. The
139 fragment is evaluated and a true value of this expression indicates that the
140 condition has been met. The event table (cust_main, cust_bill or cust_pkg) is
141 passed as an argument.
143 This method is used for optimizing event queries. You may want to add indices
144 for any columns referenced. It is acceptable to return an SQL fragment which
145 partially tests the condition; doing so will still reduce the number of
146 records which much be returned and tested with the B<condition> method.
152 my( $class, $eventtable ) = @_;
159 Condition classes may optionally define a disabled method. Returning a true
160 value disbles the condition entirely.
170 This is used internally by the I<once> and I<balance> conditions. You probably
171 do B<not> want to define this method for new custom conditions, unless you're
172 sure you want B<every> new action to start with your condition.
174 Condition classes may define an implicit_flag method that returns true to
175 indicate that all new events should start with this condition. (Currently,
176 condition classes which do so should be applicable to all kinds of
177 I<eventtable>s.) The numeric value of the flag also defines the ordering of
183 sub implicit_flag { 0; }
187 Again, used internally by the I<once> and I<balance> conditions; probably not
188 a good idea for new custom conditions.
190 Condition classes may define a remove_warning method containing a string
191 warning message to enable a confirmation dialog triggered when the condition
192 is removed from an event.
197 sub remove_warning { ''; }
201 This is used internally by the I<balance_age> and I<cust_bill_age> conditions
202 to declare ordering; probably not of general use for new custom conditions.
204 =item order_sql_weight
206 In conjunction with order_sql, this defines which order the ordering fragments
207 supplied by different B<order_sql> should be used.
211 sub order_sql_weight { ''; }
217 These methods are defined in the base class for use in condition classes.
221 =item cust_main CUST_OBJECT
223 Return the customer object (see L<FS::cust_main>) associated with the provided
224 object (the object itself if it is already a customer object).
229 my( $self, $cust_object ) = @_;
231 $cust_object->isa('FS::cust_main') ? $cust_object : $cust_object->cust_main;
235 =item option_label OPTIONNAME
237 Returns the label for the specified option name.
242 my( $self, $optionname ) = @_;
244 my %option_fields = $self->option_fields;
246 ref( $option_fields{$optionname} )
247 ? $option_fields{$optionname}->{'label'}
248 : $option_fields{$optionname}
254 =item condition_sql_option OPTION
256 This is a class method that returns an SQL fragment for retreiving a condition
257 option. It is primarily intended for use in B<condition_sql>.
261 sub condition_sql_option {
262 my( $class, $option ) = @_;
264 ( my $condname = $class ) =~ s/^.*:://;
266 "( SELECT optionvalue FROM part_event_condition_option
267 WHERE part_event_condition_option.eventconditionnum =
268 cond_$condname.eventconditionnum
269 AND part_event_condition_option.optionname = '$option'
273 =item condition_sql_option_age_from OPTION FROM_TIMESTAMP
275 This is a class method that returns an SQL fragment that will retreive a
276 condition option, parse it from a frequency (such as "1d", "1w" or "12m"),
277 and subtract that interval from the supplied timestamp. It is primarily
278 intended for use in B<condition_sql>.
282 sub condition_sql_option_age_from {
283 my( $class, $option, $from ) = @_;
285 my $value = $class->condition_sql_option($option);
287 # my $str2time = str2time_sql;
289 if ( driver_name =~ /^Pg/i ) {
291 #can we do better with Pg now that we have $from? yes we can, bob
292 "( $from - EXTRACT( EPOCH FROM REPLACE( $value, 'm', 'mon')::interval ) )";
294 } elsif ( driver_name =~ /^mysql/i ) {
296 #hmm... is there a way we can save $value? we're just an expression, hmm
297 #we might be able to do something like "AS ${option}_value" except we get
298 #used in more complicated expressions and we need some sort of unique
299 #identifer passed down too... yow
301 "CASE WHEN $value IS NULL OR $value = ''
303 WHEN $value LIKE '%m'
305 FROM_UNIXTIME($from) - INTERVAL REPLACE( $value, 'm', '' ) MONTH
307 WHEN $value LIKE '%y'
309 FROM_UNIXTIME($from) - INTERVAL REPLACE( $value, 'y', '' ) YEAR
311 WHEN $value LIKE '%w'
313 FROM_UNIXTIME($from) - INTERVAL REPLACE( $value, 'w', '' ) WEEK
315 WHEN $value LIKE '%d'
317 FROM_UNIXTIME($from) - INTERVAL REPLACE( $value, 'd', '' ) DAY
319 WHEN $value LIKE '%h'
321 FROM_UNIXTIME($from) - INTERVAL REPLACE( $value, 'h', '' ) HOUR
327 die "FATAL: don't know how to subtract frequencies from dates for ".
328 driver_name. " databases";
334 =item condition_sql_option_age OPTION
336 This is a class method that returns an SQL fragment for retreiving a condition
337 option, and additionaly parsing it from a frequency (such as "1d", "1w" or
338 "12m") into an approximate number of seconds.
340 Note that since months vary in length, the results of this method should B<not>
341 be used in computations (use condition_sql_option_age_from for that). They are
342 useful for for ordering and comparison to other ages.
344 This method is primarily intended for use in B<order_sql>.
348 sub condition_sql_option_age {
349 my( $class, $option ) = @_;
350 $class->age2seconds_sql( $class->condition_sql_option($option) );
353 =item age2seconds_sql
355 Class method returns an SQL fragment for parsing an arbitrary frequeny (such
356 as "1d", "1w", "12m", "2y" or "12h") into an approximate number of seconds.
358 Approximate meaning: months are considered to be 30 days, years to be
359 365.25 days. Otherwise the numbers of seconds returned is exact.
363 sub age2seconds_sql {
364 my( $class, $value ) = @_;
366 if ( driver_name =~ /^Pg/i ) {
368 "EXTRACT( EPOCH FROM REPLACE( $value, 'm', 'mon')::interval )";
370 } elsif ( driver_name =~ /^mysql/i ) {
372 #hmm... is there a way we can save $value? we're just an expression, hmm
373 #we might be able to do something like "AS ${option}_age" except we get
374 #used in more complicated expressions and we need some sort of unique
375 #identifer passed down too... yow
376 # 2592000 = 30d "1 month"
377 # 31557600 = 365.25d "1 year"
379 "CASE WHEN $value IS NULL OR $value = ''
381 WHEN $value LIKE '%m'
382 THEN REPLACE( $value, 'm', '' ) * 2592000
383 WHEN $value LIKE '%y'
384 THEN REPLACE( $value, 'y', '' ) * 31557600
385 WHEN $value LIKE '%w'
386 THEN REPLACE( $value, 'w', '' ) * 604800
387 WHEN $value LIKE '%d'
388 THEN REPLACE( $value, 'd', '' ) * 86400
389 WHEN $value LIKE '%h'
390 THEN REPLACE( $value, 'h', '' ) * 3600
395 die "FATAL: don't know how to approximate frequencies for ". driver_name.
402 =head1 NEW CONDITION CLASSES
404 A module should be added in FS/FS/part_event/Condition/ which implements the
405 methods desribed above in L</METHODS>. An example may be found in the
406 eg/part_event-Condition-template.pm file.