X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FReport%2FTable%2FMonthly.pm;h=0ff7efd16c43424525b706d30fd2077cc54549e1;hb=98ea15536afc6896cce08a41b877d6cb52444d14;hp=620af081e2d224fec3f537bae3bff93197427705;hpb=f360579dd091f1adf9cea1062aa06afdf5bff42b;p=freeside.git diff --git a/FS/FS/Report/Table/Monthly.pm b/FS/FS/Report/Table/Monthly.pm index 620af081e..0ff7efd16 100644 --- a/FS/FS/Report/Table/Monthly.pm +++ b/FS/FS/Report/Table/Monthly.pm @@ -1,14 +1,12 @@ package FS::Report::Table::Monthly; use strict; -use vars qw( @ISA $DEBUG ); -use Time::Local; -use FS::UID qw( dbh ); +use vars qw( @ISA ); +use FS::UID qw(dbh); use FS::Report::Table; -use FS::CurrentUser; +use Time::Local qw( timelocal ); @ISA = qw( FS::Report::Table ); -$DEBUG = 0; # turning this on will trace all SQL statements, VERY noisy =head1 NAME @@ -26,6 +24,8 @@ FS::Report::Table::Monthly - Tables of report data, indexed monthly 'end_year' => 2020, #opt 'agentnum' => 54 + 'refnum' => 54 + 'cust_classnum' => [ 1,2,4 ], 'params' => [ [ 'paramsfor', 'item_one' ], [ 'item', 'two' ] ], # ... 'remove_empty' => 1, #collapse empty rows, default 0 'item_labels' => [ ], #useful with remove_empty @@ -33,555 +33,270 @@ FS::Report::Table::Monthly - Tables of report data, indexed monthly my $data = $report->data; -=head1 METHODS +=head1 PARAMETERS -=over 4 +=head2 TIME PERIOD -=item data +C, C, C, and C specify the date +range to be included in the report. The start and end months are included. +Each month's values are summed from midnight on the first of the month to +23:59:59 on the last day of the month. -Returns a hashref of data (!! describe) +=head2 REPORT ITEMS -=cut +=over 4 -sub data { - my $self = shift; +=item items: An arrayref of observables to calculate for each month. See +L for a list of observables and their parameters. - #use Data::Dumper; - #warn Dumper($self); +=item params: An arrayref, parallel to C, of arrayrefs of parameters +(in paired name/value form) to be passed to the observables. - my $smonth = $self->{'start_month'}; - my $syear = $self->{'start_year'}; - my $emonth = $self->{'end_month'}; - my $eyear = $self->{'end_year'}; - my $agentnum = $self->{'agentnum'}; +=item cross_params: Cross-product parameters. This must be an arrayref of +arrayrefs of parameters (paired name/value form). This creates an additional +"axis" (orthogonal to the time and C axes) in which the item is +calculated once with each set of parameters in C. These +parameters are merged with those in C. Instead of being nested two +levels, C will be nested three levels, with the third level +corresponding to this arrayref. - my %data; +=back - while ( $syear < $eyear || ( $syear == $eyear && $smonth < $emonth+1 ) ) { +=head2 FILTERING - push @{$data{label}}, "$smonth/$syear"; +=over 4 - my $speriod = timelocal(0,0,0,1,$smonth-1,$syear); - push @{$data{speriod}}, $speriod; - if ( ++$smonth == 13 ) { $syear++; $smonth=1; } - my $eperiod = timelocal(0,0,0,1,$smonth-1,$syear); - push @{$data{eperiod}}, $eperiod; - - my $col = 0; - my @row = (); - foreach my $item ( @{$self->{'items'}} ) { - my @param = $self->{'params'} ? @{ $self->{'params'}[$col] }: (); - my $value = $self->$item($speriod, $eperiod, $agentnum, @param); - #push @{$data{$item}}, $value; - push @{$data{data}->[$col++]}, $value; - } +=item agentnum: Limit to customers with this agent. - } +=item refnum: Limit to customers with this advertising source. - #these need to get generalized, sheesh - $data{'items'} = $self->{'items'}; - $data{'item_labels'} = $self->{'item_labels'} || $self->{'items'}; - $data{'colors'} = $self->{'colors'}; - $data{'links'} = $self->{'links'} || []; +=item cust_classnum: Limit to customers with this classnum; can be an +arrayref. - #use Data::Dumper; - #warn Dumper(\%data); +=item remove_empty: Set this to a true value to hide rows that contain +only zeroes. The C array in the returned data will list the item +indices that are actually present in the output so that you know what they +are. Ignored if C is in effect. - if ( $self->{'remove_empty'} ) { +=back - #warn "removing empty rows\n"; +=head2 PASS-THROUGH - my $col = 0; - #these need to get generalized, sheesh - my @newitems = (); - my @newlabels = (); - my @newdata = (); - my @newcolors = (); - my @newlinks = (); - foreach my $item ( @{$self->{'items'}} ) { +C, C, and C may be specified as arrayrefs +parallel to C. Those values will be returned in C, with any +hidden rows (due to C) filtered out, which is the only +reason to do this. Now that we have C it's probably better to +use that. - if ( grep { $_ != 0 } @{$data{'data'}->[$col]} ) { - push @newitems, $data{'items'}->[$col]; - push @newlabels, $data{'item_labels'}->[$col]; - push @newdata, $data{'data'}->[$col]; - push @newcolors, $data{'colors'}->[$col]; - push @newlinks, $data{'links'}->[$col]; - } +=item PROCESSING - $col++; - } - - $data{'items'} = \@newitems; - $data{'item_labels'} = \@newlabels; - $data{'data'} = \@newdata; - $data{'colors'} = \@newcolors; - $data{'links'} = \@newlinks; +=item normalize: Set this to an item index to have all other items expressed +as a percentage of that one. That item will then be omitted from the output. +If the normalization item is zero in some period, all the values in that +period will be undef. - } +=head1 RETURNED DATA - #use Data::Dumper; - #warn Dumper(\%data); +The C method runs the report and returns a hashref of the following: - \%data; +=over 4 -} +=item label -sub invoiced { #invoiced - my( $self, $speriod, $eperiod, $agentnum ) = @_; +Month labels, in MM/YYYY format. - $self->scalar_sql(" - SELECT SUM(charged) - FROM cust_bill - LEFT JOIN cust_main USING ( custnum ) - WHERE ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum) - ); - -} +=item speriod, eperiod -sub netsales { #net sales - my( $self, $speriod, $eperiod, $agentnum ) = @_; +Absolute start and end times of each month, in unix time format. - $self->invoiced($speriod,$eperiod,$agentnum) - - $self->credits( $speriod,$eperiod,$agentnum); -} +=item items -#deferred revenue +The values passed in as C, with any suppressed rows deleted. -sub cashflow { - my( $self, $speriod, $eperiod, $agentnum ) = @_; +=item indices - $self->payments($speriod, $eperiod, $agentnum) - - $self->refunds( $speriod, $eperiod, $agentnum); -} +The indices of items in the input C list that appear in the result +set. Useful for figuring out what they are when C has deleted +some items. -sub netcashflow { - my( $self, $speriod, $eperiod, $agentnum ) = @_; +=item item_labels, colors, links - see PASS-THROUGH above - $self->receipts($speriod, $eperiod, $agentnum) - - $self->netrefunds( $speriod, $eperiod, $agentnum); -} +=item data -sub payments { - my( $self, $speriod, $eperiod, $agentnum ) = @_; - $self->scalar_sql(" - SELECT SUM(paid) - FROM cust_pay - LEFT JOIN cust_main USING ( custnum ) - WHERE ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum) - ); -} +The actual results. An arrayref corresponding to C