sub description { 'Customer balance age'; }
+=item check_options OPTIONS
+
+Validate options
+
+=cut
+
+my $duration_rx = qr/^(\d+)$/;
+my $unit_rx = qr/^[wmdh]$/;
+my $both_rx = qr/^(\d+)([wmdh])/;
+
+sub check_options {
+ my ($self, $options) = @_;
+
+ my $age = $options->{age};
+ my $age_units = $options->{age_units};
+
+ return "Invalid (age) must be defined: $age"
+ unless( defined $age );
+
+ # over-ride possibly inaccurate unit indicator
+ if( $age =~ /$both_rx/ ){
+ $age = $1;
+ $age_units = $2;
+ }
+
+ return "Invalid (age_units) must be defined: $age_units"
+ unless defined $age_units;
+
+ return "Invalid (age) must be integer: $age"
+ unless( $age =~ /$duration_rx/ );
+
+ return "Invalid (age) must be non-zero: $age"
+ if ( $age == 0 );
+
+ return( "Invalid (age_units) must be m/w/d/h: $age_units" )
+ unless( $age_units =~ /$unit_rx/i );
+
+ return '';
+}
+
sub option_fields {
(
'balance' => { 'label' => 'Balance over',
if ( $cgi->param('_initialize') ) {
$cgi->param('disabled', 'Y');
}
+
+ my $balance_age_rx = qr/^(condition.+)\.balance_age\.age$/;
+
+ foreach my $param ( keys %{ $cgi->Vars() } ){
+
+ next unless ( $param =~ /$balance_age_rx/ );
+ next unless $cgi->param($1) eq 'balance_age';
+
+ my $errstr = FS::part_event::Condition::balance_age->
+ check_options( { age => $cgi->param($param),
+ age_units => $cgi->param("${param}_units") } );
+
+ return $errstr if $errstr;
+ }
+
return '';
},
'noerror_callback' => sub {
$report_customers{'List customers'} = [ \%report_customers_lists, 'List customers' ]
if $curuser->access_right('List all customers');
$report_customers{'Zip code distribution'} = [ $fsurl. 'search/report_cust_main-zip.html', 'Zip codes by number of customers' ];
-$report_customers{'Customer signup report'} = [ $fsurl. 'graph/report_cust_signup.html', 'New customer signups by date' ],
-$report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_main.html', 'by status, signup date, agent, etc.' ]
+$report_customers{'Customer signup report'} = [ $fsurl. 'graph/report_cust_signup.html', 'New customer signups by date' ];
+$report_customers{'Signup date report'} = [ $fsurl. 'graph/report_signupdate.html', 'Signup date report (by date of signup)' ];
+$report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_main.html', 'by status, signup date, agent, etc.' ]
if $curuser->access_right('Advanced customer search');
tie my %report_invoices_open, 'Tie::IxHash',
my %where;
$where{'agentnum'} = $agentnum if $agentnum;
$where{'usernum'} = $usernum if $usernum;
-my $sdate = $cgi->param('start_year').
- '-'.
- $cgi->param('start_month').
- '-01';
-my $edate = ($cgi->param('end_year') +
- ($cgi->param('end_month')==12)).
- '-'.
- ($cgi->param('end_month') % 12 + 1).
- '-01'; # first day of the next month
-
-my $sql = "AND signupdate >= ".str2time($sdate).
- " AND signupdate < ".str2time($edate);
+
+my $sdate = DateTime->new(
+ year => $cgi->param('start_year'),
+ month => $cgi->param('start_month'),
+)->epoch();
+
+my $edate = DateTime->new(
+ year => $cgi->param('end_year'),
+ month => ($cgi->param('end_month') % 12 + 1) # first day of the next month
+)->epoch();
+
+my $where .= " AND signupdate >= $sdate ".
+ " AND signupdate <= $edate ";
foreach my $cust (qsearch({ table => 'cust_main',
hashref => \%where,
- extra_sql => $sql } )) {
+ extra_sql => $where } )) {
next if !$cust->signupdate;
my $hour = time2str('%H',$cust->signupdate);
$count[$hour]++;