X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=httemplate%2Fsearch%2Fcustomer_accounting_summary.html;h=5ce2e3a8f02b9d3d1fbebbef4a8d518c15e98890;hp=72a00ed957d4deef8adad0cd03a3f366ac75fd76;hb=044e4ea5533f1c14697b7ad408dc0cf0e0327abb;hpb=c673787bf1ac56408e589ed20ea63404e9181574 diff --git a/httemplate/search/customer_accounting_summary.html b/httemplate/search/customer_accounting_summary.html index 72a00ed95..5ce2e3a8f 100644 --- a/httemplate/search/customer_accounting_summary.html +++ b/httemplate/search/customer_accounting_summary.html @@ -1,25 +1,124 @@ -<% include('/graph/elements/monthly.html', - #Dumper( - 'title' => $title, - 'graph_type' => 'none', - 'items' => \@items, - 'params' => \@params, - 'labels' => \@labels, - 'graph_labels' => \@labels, - 'remove_empty' => 1, - 'bottom_total' => 1, - 'agentnum' => $agentnum, - 'doublemonths' => \@doublemonths, - 'nototal' => 1, - ) -%> +% if ( $cgi->param('_type') =~ /(xls)$/ ) { +<%perl> + # egregious false laziness w/ search/report_tax-xls.cgi + my $format = $FS::CurrentUser::CurrentUser->spreadsheet_format; + my $filename = $cgi->url(-relative => 1); + $filename =~ s/\.html$//; + $filename .= $format->{extension}; + http_header('Content-Type' => $format->{mime_type}); + http_header('Content-Disposition' => qq!attachment;filename="$filename"!); + + my $output = ''; + use IO::String; + my $XLS = IO::String->new($output);; + my $workbook = $format->{class}->new($XLS) + or die "Error opening .xls file: $!"; + + my $worksheet = $workbook->add_worksheet('Summary'); + + my %format = ( + header => { + size => 11, + bold => 1, + align => 'center', + valign => 'vcenter', + text_wrap => 1, + }, + money => { + size => 11, + align => 'right', + valign => 'bottom', + num_format=> 8, + }, + '' => {}, + ); + my %default = ( + font => 'Calibri', + border => 1, + ); + foreach (keys %format) { + my %f = (%default, %{$format{$_}}); + $format{$_} = $workbook->add_format(%f); + $format{"m_$_"} = $workbook->add_format(%f); + } + + my ($r, $c) = (0, 0); + for my $row (@rows) { + $c = 0; + my $thisrow = shift @cells; + for my $cell (@$thisrow) { + if (!ref($cell)) { + # placeholder, so increment $c so that we write to the correct place + $c++; + next; + } + # format name + my $f = ''; + $f = 'header' if $row->{header} or $cell->{header}; + $f = 'money' if $cell->{format} eq 'money'; + if ( $cell->{rowspan} > 1 or $cell->{colspan} > 1 ) { + my $range = xl_range_formula( + 'Summary', + $r, $r - 1 + ($cell->{rowspan} || 1), + $c, $c - 1 + ($cell->{colspan} || 1) + ); + #warn "merging $range\n"; + $worksheet->merge_range($range, $cell->{value}, $format{"m_$f"}); + } else { + #warn "writing ".xl_rowcol_to_cell($r, $c)."\n"; + $worksheet->write( $r, $c, $cell->{value}, $format{$f} ); + } + $c++; + } #$cell + $r++; + } #$row + $workbook->close; + +<% $output %> +% } else { +<& /elements/header.html, $title &> +% my $myself = $cgi->self_url; +

+Download full reports
+as ">Excel spreadsheet
+% # as ">CSV file # is this still needed? +

+ + +% foreach my $rowinfo (@rows) { + {class} ? ' class="'.$rowinfo->{class}.'"' : ''%>> +% my $thisrow = shift @cells; +% foreach my $cell (@$thisrow) { +% next if !ref($cell); # placeholders +% my $td = $cell->{header} ? 'th' : 'td'; +% my $style = ''; +% $style .= " rowspan=".$cell->{rowspan} if $cell->{rowspan} > 1; +% $style .= " colspan=".$cell->{colspan} if $cell->{colspan} > 1; + <<%$td%><%$style%>><% $cell->{value} %>> +% } + +% } +
+ +<& /elements/footer.html &> +% } <%init> die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); -my @doublemonths = ( 'Billed', 'Paid' ); - my ($agentnum,$sel_agent); if ( $cgi->param('agentnum') eq 'all' ) { $agentnum = 0; @@ -32,9 +131,6 @@ elsif ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { my $title = $sel_agent ? $sel_agent->agent.' ' : ''; my ($refnum,$sel_part_referral); -#if ( $cgi->param('refnum') eq 'all' ) { -# $refnum = 0; -#} els if ( $cgi->param('refnum') =~ /^(\d+)$/ ) { $refnum = $1; $sel_part_referral = qsearchs('part_referral', { 'refnum' => $refnum } ); @@ -46,28 +142,158 @@ $title .= $sel_part_referral->referral.' ' $title .= 'Customer Accounting Summary Report'; my @custs = (); -@custs = qsearch('cust_main', {} ); +@custs = qsearch('cust_main', {} ); -my @items = (); -my @params = (); +my @items = ('netsales', 'cashflow'); +my @params = ( [], [] ); +my $setuprecur = ''; +if ( $cgi->param('setuprecur') ) { + $setuprecur = 1; + # instead of 'cashflow' (payments - refunds), use 'receipts' + # (applied payments), because it's divisible into setup and recur. + @items = ('netsales', 'receipts', 'netsales', 'receipts'); + @params = ( + [ setuprecur => 'setup' ], + [ setuprecur => 'setup' ], + [ setuprecur => 'recur' ], + [ setuprecur => 'recur' ], + ); +} my @labels = (); +my @cross_params = (); +my @custnames = (); my $status = $cgi->param('status'); die "invalid status" unless $status =~ /^\w+|$/; foreach my $cust_main ( @custs ) { + # XXX should do this in the qsearch next unless ($status eq '' || $status eq $cust_main->status); next unless ($agentnum == 0 || $cust_main->agentnum eq $agentnum); next unless ($refnum == 0 || $cust_main->refnum eq $refnum); - push @items, 'netsales', 'cashflow'; + push @custnames, $cust_main->name; - push @labels, $cust_main->name; + push @cross_params, [ ('custnum' => $cust_main->custnum) ]; +} + +my %opt = ( + items => \@items, + params => \@params, + cross_params => \@cross_params, + agentnum => $agentnum, + refnum => $refnum, +); +for ( qw(start_month start_year end_month end_year) ) { + if ( $cgi->param($_) =~ /^(\d+)$/ ) { + $opt{$_} = $1; + } +} + +warn Dumper(OPTIONS => \%opt) if $cgi->param('debug'); +my $report = FS::Report::Table::Monthly->new(%opt); +my $data = $report->data; +warn Dumper(DATA => $data) if $cgi->param('debug') >= 2; + +my @total; + +my @rows; # hashes of row info +my @cells; # arrayrefs of cell info +# We use Excel currency format, but not Excel dates, because +# these are whole months and there's no nice way to express that. +# This is the historical behavior for monthly reports. + +# header row +$rows[0] = {}; +$cells[0] = [ + { header => 1, rowspan => 2, colspan => ($setuprecur ? 2 : 1) }, + ($setuprecur ? '' : ()), + map { + { header => 1, colspan => 2, value => time2str('%b %Y', $_) }, + '' + } @{ $data->{speriod} } +]; +my $ncols = scalar(@{ $data->{speriod} }); + +$rows[1] = {}; +$cells[1] = [ '', + ($setuprecur ? '' : ()), + map { + ( { header => 1, value => mt('Billed') }, + { header => 1, value => mt('Paid') } + ) } (1..$ncols) +]; + +# use PDL; # ha ha, I just might. +my $row = 0; +foreach my $name (@custnames) { # correspond to cross_params + my $skip = 1; # skip the customer iff ALL of their values are zero + for my $subrow (0..($setuprecur ? 1 : 0)) { # the setup/recur axis + push @rows, { class => $subrow ? 'shaded' : '' }; + my @thisrow; + if ( $subrow == 0 ) { + # customer name + push @thisrow, + { value => $name, + header => 1, + rowspan => ($setuprecur ? 2 : 1) }; + } else { + push @thisrow, ''; + } + if ( $setuprecur ) { + # subheading + push @thisrow, + { value => $subrow ? mt('recurring') : mt('setup'), + header => 1 }; + } + for my $col (0..$ncols-1) { # the month + for my $subcol (0..1) { # the billed/paid axis + my $item = $subrow * 2 + $subcol; + my $value = $data->{data}[$item][$col][$row]; + $skip = 0 if abs($value) > 0.005; + push @thisrow, { value => sprintf('%0.2f', $value), format => 'money' }; + $total[( ($ncols * $subrow) + $col ) * 2 + $subcol] += $value; + } #subcol + } #col + push @cells, \@thisrow; + } #subrow + if ( $skip ) { + # all values are zero--remove the rows we just added + pop @rows; + pop @cells; + if ( $setuprecur ) { + pop @rows; + pop @cells; + } + } + $row++; +} +for my $subrow (0..($setuprecur ? 1 : 0)) { + push @rows, { class => ($subrow ? 'totalshaded' : 'total') }; + my @thisrow; + if ( $subrow == 0 ) { + push @thisrow, + { value => mt('Total'), + header => 1, + rowspan => ($setuprecur ? 2 : 1), }; + } else { + push @thisrow, ''; + } + if ( $setuprecur ) { + push @thisrow, + { value => $subrow ? mt('recurring') : mt('setup'), + header => 1 }; + } + for my $col (0..($ncols * 2)-1) { # month and billed/paid axis + my $value = $total[($subrow * $ncols * 2) + $col]; + push @thisrow, { value => sprintf('%0.2f', $value), format => 'money' }; + } + push @cells, \@thisrow; +} #subrow - push @params, [ ('custnum' => $cust_main->custnum), - ], - [ ('custnum' => $cust_main->custnum), - ]; +if ( $cgi->param('debug') >= 3 ) { + warn Dumper(\@rows, \@cells); } +my $title = 'Customer Accounting Summary';