qsearch('cust_location', { 'custnum' => $self->custnum } );
}
+=item location_label_short
+
+Returns the short label of the service location (see analog in L<FS::cust_location>) for this customer.
+
+=cut
+
+# false laziness with FS::cust_location::line_short
+
+sub location_label_short {
+ my $self = shift;
+ my $cydefault = FS::conf->new->config('countrydefault') || 'US';
+
+ my $line = $self->address1;
+ #$line .= ', '. $self->address2 if $self->address2;
+ $line .= ', '. $self->city;
+ $line .= ', '. $self->state if $self->state;
+ $line .= ' '. $self->zip if $self->zip;
+ $line .= ' '. code2country($self->country) if $self->country ne $cydefault;
+
+ $line;
+}
+
=item ncancelled_pkgs [ EXTRA_QSEARCH_PARAMS_HASHREF ]
Returns all non-cancelled packages (see L<FS::cust_pkg>) for this customer.
# This should be generalized to use config options to determine order.
sub sort_packages {
+ my $locationsort = $a->locationnum <=> $b->locationnum;
+ return $locationsort if $locationsort;
+
if ( $a->get('cancel') xor $b->get('cancel') ) {
return -1 if $b->get('cancel');
return 1 if $a->get('cancel');
=item invoice_terms
-Options terms to be printed on this invoice. Otherwise, customer-specific
+Optional terms to be printed on this invoice. Otherwise, customer-specific
terms or the default terms are used.
=back
);
}
+=item balance_date_range START_TIME [ END_TIME [ OPTION => VALUE ... ] ]
+
+Returns the balance for this customer, only considering invoices with date
+earlier than START_TIME, and optionally not later than END_TIME
+(total_owed_date minus total_unapplied_credits minus total_unapplied_payments).
+
+Times are specified as SQL fragments or numeric
+UNIX timestamps; see L<perlfunc/"time">). Also see L<Time::Local> and
+L<Date::Parse> for conversion functions. The empty string can be passed
+to disable that time constraint completely.
+
+Available options are:
+
+=over 4
+
+=item unapplied_date
+
+set to true to disregard unapplied credits, payments and refunds outside the specified time period - by default the time period restriction only applies to invoices (useful for reporting, probably a bad idea for event triggering)
+
+=back
+
+=cut
+
+sub balance_date_range {
+ my $self = shift;
+ my $sql = 'SELECT SUM('. $self->balance_date_sql(@_).
+ ') FROM cust_main WHERE custnum='. $self->custnum;
+ sprintf( "%.2f", $self->scalar_sql($sql) );
+}
+
=item balance_pkgnum PKGNUM
Returns the balance for this customer's specific package when using
}
-=item search_sql HASHREF
+=item search HASHREF
(Class method)
=cut
-sub search_sql {
+sub search {
my ($class, $params) = @_;
my $dbh = dbh;
# classnum
###
- my @classnum = grep /^(\d*)$/, @{ $params->{'classnum'} };
- if ( @classnum ) {
- push @where, '( '. join(' OR ', map {
- $_ ? "cust_main.classnum = $_"
- : "cust_main.classnum IS NULL"
- }
- @classnum
- ).
- ' )';
+ if ( $params->{'classnum'} ) {
+
+ my @classnum = ref( $params->{'classnum'} )
+ ? @{ $params->{'classnum'} }
+ : ( $params->{'classnum'} );
+
+ @classnum = grep /^(\d*)$/, @classnum;
+
+ if ( @classnum ) {
+ push @where, '( '. join(' OR ', map {
+ $_ ? "cust_main.classnum = $_"
+ : "cust_main.classnum IS NULL"
+ }
+ @classnum
+ ).
+ ' )';
+ }
+
}
###
# payby
###
- my @payby = grep /^([A-Z]{4})$/, @{ $params->{'payby'} };
- if ( @payby ) {
- push @where, '( '. join(' OR ', map "cust_main.payby = '$_'", @payby). ' )';
+ if ( $params->{'payby'} ) {
+
+ my @payby = ref( $params->{'payby'} )
+ ? @{ $params->{'payby'} }
+ : ( $params->{'payby'} );
+
+ @payby = grep /^([A-Z]{4})$/, @{ $params->{'payby'} };
+
+ push @where, '( '. join(' OR ', map "cust_main.payby = '$_'", @payby). ' )'
+ if @payby;
+
}
###
# amounts
##
- #my $balance_sql = $class->balance_sql();
- my $balance_sql = FS::cust_main->balance_sql();
+ if ( $params->{'current_balance'} ) {
+
+ #my $balance_sql = $class->balance_sql();
+ my $balance_sql = FS::cust_main->balance_sql();
- my @current_balance = @{ $params->{'current_balance'} };
+ my @current_balance =
+ ref( $params->{'current_balance'} )
+ ? @{ $params->{'current_balance'} }
+ : ( $params->{'current_balance'} );
- push @where, map { s/current_balance/$balance_sql/; $_ }
- @current_balance;
+ push @where, map { s/current_balance/$balance_sql/; $_ }
+ @current_balance;
+
+ }
##
# custbatch
}
-=item email_search_sql HASHREF
+=item email_search_result HASHREF
(Class method)
Emails a notice to the specified customers.
-Valid parameters are those of the L<search_sql> method, plus the following:
+Valid parameters are those of the L<search> method, plus the following:
=over 4
=cut
-sub email_search_sql {
+sub email_search_result {
my($class, $params) = @_;
my $from = delete $params->{from};
$params->{'payby'} = [ split(/\0/, $params->{'payby'}) ]
unless ref($params->{'payby'});
- my $sql_query = $class->search_sql($params);
+ my $sql_query = $class->search($params);
my $count_query = delete($sql_query->{'count_query'});
my $count_sth = dbh->prepare($count_query)
use Storable qw(thaw);
use Data::Dumper;
use MIME::Base64;
-sub process_email_search_sql {
+sub process_email_search_result {
my $job = shift;
#warn "$me process_re_X $method for job $job\n" if $DEBUG;
$param->{'payby'} = [ split(/\0/, $param->{'payby'}) ]
unless ref($param->{'payby'});
- my $error = FS::cust_main->email_search_sql( $param );
+ my $error = FS::cust_main->email_search_result( $param );
die $error if $error;
}
#getting complaints searches are not returning enough
unless ( @cust_main && $skip_fuzzy || $conf->exists('disable-fuzzy') ) {
- #still some false laziness w/search_sql (was search/cust_main.cgi)
+ #still some false laziness w/search (was search/cust_main.cgi)
#substring