% include('elements/monthly.html',
                'title'        => $title,
                'graph_type'   => $graph_type,
                'items'        => \@items,
                'params'       => \@params,
                'labels'       => \@labels,
                'graph_labels' => \@labels,
                'colors'       => \@colors,
                'links'        => \@links,
                'no_graph'     => \@no_graph,
                'remove_empty' => 1,
                'bottom_total' => $show_total,
                'nototal'      => !$show_total,
                'bottom_link'  => $bottom_link,
                'agentnum'     => $agentnum,
                'cust_classnum'=> \@cust_classnums,
             )
%>
<%init>
die "access denied"
  unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
my $link = "${p}search/cust_bill_pkg.cgi?nottax=1";
my $bottom_link = "$link;";
my $use_usage = $cgi->param('use_usage') || 0;
my $use_setup = $cgi->param('use_setup') || 0;
my $use_discount = $cgi->param('use_discount') || 2;
my $use_taxes = $cgi->param('use_taxes') || 0;
my $use_override         = $cgi->param('use_override')         ? 1 : 0;
my $average_per_cust_pkg = $cgi->param('average_per_cust_pkg') ? 1 : 0;
my $distribute           = $cgi->param('distribute')           ? 1 : 0;
my $show_total = 1;
my $graph_type = 'Mountain';
if ( $average_per_cust_pkg ) {
  # then the rows are not additive
  $show_total = 0;
  $graph_type = 'LinesPoints';
}
my %charge_labels = (
  'SRU'=> 'setup + recurring',
  'SR' => 'setup + recurring',
  'RU' => 'recurring',
  'S'  => 'setup',
  'R'  => 'recurring',
  'U'  => 'usage',
  'D'  => 'discount',
  'T'  => 'taxes',
);
#XXX or virtual
my( $agentnum, $sel_agent, $all_agent ) = ('', '', '');
if ( $cgi->param('agentnum') eq 'all' ) {
  $agentnum = 0;
  $all_agent = 'ALL';
}
elsif ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
  $agentnum = $1;
  $bottom_link .= "agentnum=$agentnum;";
  $sel_agent = qsearchs('agent', { 'agentnum' => $agentnum } );
  die "agentnum $agentnum not found!" unless $sel_agent;
}
my $title = $sel_agent ? $sel_agent->agent.' ' : '';
my( $refnum, $sel_part_referral, $all_part_referral ) = ('', '', '');
if ( $cgi->param('refnum') eq 'all' ) {
  $refnum = 0;
  $all_part_referral = 'ALL';
}
elsif ( $cgi->param('refnum') =~ /^(\d+)$/ ) {
  $refnum = $1;
  $bottom_link .= "refnum=$refnum;";
  $sel_part_referral = qsearchs('part_referral', { 'refnum' => $refnum } );
  die "part_referral $refnum not found!" unless $sel_part_referral;
}
$title .= $sel_part_referral->referral.' '
  if $sel_part_referral;
$title .= 'Sales Report (Gross)';
$title .= ', average per customer package'  if $average_per_cust_pkg;
my @cust_classnums = grep /^\d+$/, $cgi->param('cust_classnum');
$bottom_link .= "cust_classnum=$_;" foreach @cust_classnums;
#classnum (here)
# not specified: no longer happens (unless you de-select all classes)
# 0: empty class
# N: classnum
#classnum (link)
# not specified: all classes
# 0: empty class
# N: classnum
#started out as false lazinessish w/FS::cust_pkg::search_sql (previously search/cust_pkg.cgi), but not much left the sane now after #24776
my ($class_table, $name_col, $value_col, $class_param);
my $all_report_options;
if ( $cgi->param('class_mode') eq 'report' ) {
  $class_param = 'report_optionnum'; # CGI param name, also used in the report engine
  $class_table = 'part_pkg_report_option'; # table containing classes
  $name_col = 'name'; # the column of that table containing the label
  $value_col = 'num'; # the column containing the class number
  # in 'exact' mode we want to run the query in ALL mode.
  # in 'breakdown' mode want to run the query in ALL mode but using the 
  # power set of the classes selected.
  $all_report_options = 1
    unless $cgi->param('class_agg_break') eq 'aggregate';
} else { # class_mode eq 'pkg'
  $class_param = 'classnum';
  $class_table = 'pkg_class';
  $name_col = 'classname';
  $value_col = 'classnum';
}
my @classnums = sort {$a <=> $b} grep /^\d+$/, $cgi->param($class_param);
my @classnames = map { if ( $_ ) {
                         my $class = qsearchs($class_table, {$value_col=>$_} );
                         $class->$name_col;
                       } else {
                         '(empty class)';
                       }
                     }
                   @classnums;
my @not_classnums;
$bottom_link .= "$class_param=$_;" foreach @classnums;
if ( $cgi->param('class_agg_break') eq 'aggregate' or
     $cgi->param('class_agg_break') eq 'exact' ) {
  $title .= ' '. join(', ', @classnames)
    unless scalar(@classnames) > scalar(qsearch($class_table,{'disabled'=>''}));
                                 #not efficient for lots of package classes
} elsif ( $cgi->param('class_agg_break') eq 'breakdown' ) {
  if ( $cgi->param('class_mode') eq 'report' ) {
    # The new way:
    # Actually break down all subsets of the (selected) report classes.
    my @subsets = FS::part_pkg_report_option->subsets(@classnums);
    my @classnum_space = @classnums;
    @classnums = @classnames = ();
    while(@subsets) {
      my $these = shift @subsets;
      # applied topology!
      my $not_these = [ @classnum_space ];
      my $i = 0;
      foreach (@$these) {
        $i++ until $not_these->[$i] == $_;
        splice(@$not_these, $i, 1);
      }
      push @classnums, $these;
      push @not_classnums, $not_these;
      push @classnames, shift @subsets;
    } #while subsets
  }
  # else it's 'pkg', i.e. part_pkg.classnum, which is singular on pkgpart
  # and much simpler
} else {
  die "guru meditation #434";
}
#eslaf
my @items  = ();
my @params = ();
my @labels = ();
my @colors = ();
my @links  = ();
my @no_graph;
my @components = ( 'SRU' );
# split/omit components as appropriate
if ( $use_setup == 1 ) {
  @components = ( 'S', 'RU' );
}
elsif ( $use_setup == 2 ) {
  @components = ( 'RU' );
}
if ( $use_usage == 1 ) {
  $components[-1] =~ s/U//; push @components, 'U';
}
elsif ( $use_usage == 2 ) {
  $components[-1] =~ s/U//;
}
if ( $use_discount == 1 ) {
  push @components, 'D';
} # else leave discounts off entirely; never combine them with setup/recur
# could in theory combine with setup/recur/usage,
# but would require reverse engineering the tax calculation
if ( $use_taxes == 1 ) {
  push @components, 'T';
} 
# Categorization of line items goes
# Agent -> Referral -> Package class -> Component (setup/recur/usage/discount/taxes)
# If per-agent totals are enabled, they go under the Agent level.
# There aren't any other kinds of subtotals.
my $anum = 0;
foreach my $agent ( $all_agent || $sel_agent || $FS::CurrentUser::CurrentUser->agents ) {
  my @agent_colors = map { my $col = $cgi->param("agent$anum-color$_");
                           $col =~ s/^#//;
                           $col;
                         }
                       (0 .. 5);
  my @colorbuf = ();
  ### fixup the color handling for package classes...
  ### and usage
  foreach my $part_referral (
    $all_part_referral ||
    $sel_part_referral ||
    qsearch('part_referral', { 'disabled' => '' } ) 
  ) {
    my @base_params = (
                        'use_override'         => $use_override,
                        'average_per_cust_pkg' => $average_per_cust_pkg,
                        'distribute'           => $distribute,
                      );
    if ( $cgi->param('class_agg_break') eq 'aggregate' or
         $cgi->param('class_agg_break') eq 'exact' ) {
      # the only difference between 'aggregate' and 'exact' is whether
      # we pass the 'all_report_options' flag.
      foreach my $component ( @components ) {
        push @items, 'cust_bill_pkg';
        push @labels,
          ( $all_agent || $sel_agent ? '' : $agent->agent.' ' ).
          ( $all_part_referral || $sel_part_referral ? '' : $part_referral->referral.' ' ).
          $charge_labels{$component};
        my $row_agentnum = $all_agent || $agent->agentnum;
        my $row_refnum = $all_part_referral || $part_referral->refnum;
        my @row_params = (
                        @base_params,
                        $class_param => \@classnums,
                        ($all_agent ? () : ('agentnum' => $row_agentnum) ),
                        ($all_part_referral ? () : ('refnum' => $row_refnum) ),
                        'charges'               => $component,
        );
        my $row_link = "$link;".
                       "charges=$component;".
                       "distribute=$distribute;";
        if ( $component eq 'D' ) {
          # discounts ignore 'charges' and 'distribute'
          $row_link = "${p}search/cust_bill_pkg_discount.html?";
        } elsif ( $component eq 'T' ) {
          $row_link = "${p}search/cust_bill_pkg.cgi?istax=1;";
        }
        $row_link .=  ($all_agent ? '' : "agentnum=$row_agentnum;").
                      ($all_part_referral ? '' : "refnum=$row_refnum;").
                      (join('',map {"cust_classnum=$_;"} @cust_classnums)).
                      "use_override=$use_override;";
        $row_link .= "$class_param=$_;" foreach @classnums;
        if ( $all_report_options ) {
          push @row_params, 'all_report_options', 1;
          $row_link .= 'all_report_options=1';
        }
        push @params, \@row_params;
        push @links, $row_link;
        @colorbuf = @agent_colors unless @colorbuf;
        push @colors, shift @colorbuf;
        push @no_graph, 0;
      } #foreach $component
    } elsif ( $cgi->param('class_agg_break') eq 'breakdown' ) {
      for (my $i = 0; $i < scalar @classnums; $i++) {
        my $row_classnum = $classnums[$i];
        my $row_classname = $classnames[$i];
        my $not_row_classnum = '';
        if ( $class_param eq 'report_optionnum' ) {
          # if we're working with report options, @classnums here contains 
          # arrays of multiple classnums
          $row_classnum = join(',', @$row_classnum);
          $row_classname = join(', ', @$row_classname);
          $not_row_classnum = join(',', @{ $not_classnums[$i] });
        }
        foreach my $component ( @components ) {
          push @items, 'cust_bill_pkg';
          push @labels,
            ( $all_agent || $sel_agent ? '' : $agent->agent.' ' ).
            ( $all_part_referral || $sel_part_referral ? '' : $part_referral->referral.' ' ).
            $row_classname .  ' ' . $charge_labels{$component};
          my $row_agentnum = $all_agent || $agent->agentnum;
          my $row_refnum = $all_part_referral || $part_referral->refnum;
          my @row_params = (
                          @base_params,
                          $class_param => $row_classnum,
                          ($all_agent ? () : ('agentnum' => $row_agentnum) ),
                          ($all_part_referral ? () : ('refnum' => $row_refnum)),
                          'charges'              => $component,
          );
          my $row_link = "$link;".
                       "charges=$component;".
                       "distribute=$distribute;";
          if ( $component eq 'D' ) {
            # discounts ignore 'charges' and 'distribute'
            $row_link ="${p}search/cust_bill_pkg_discount.html?";
          } elsif ( $component eq 'T' ) {
            $row_link = "${p}search/cust_bill_pkg.cgi?istax=1;";
          }
          $row_link .= ($all_agent ? '' : "agentnum=$row_agentnum;").
                       ($all_part_referral ? '' : "refnum=$row_refnum;").
                       (join('',map {"cust_classnum=$_;"} @cust_classnums)).
                       "$class_param=$row_classnum;".
                       "use_override=$use_override;";
          if ( $class_param eq 'report_optionnum' ) {
            push @row_params,
                          'all_report_options' => 1,
                          'not_report_optionnum' => $not_row_classnum,
            ;
            $row_link .= "all_report_options=1;".
                         "not_report_optionnum=$not_row_classnum;";
          }
          push @params, \@row_params;
          push @links, $row_link;
          @colorbuf = @agent_colors unless @colorbuf;
          push @colors, shift @colorbuf;
          push @no_graph, 0;
        } #foreach $component
      } #foreach $row_classnum
    } #$cgi->param('class_agg_break')
  } #foreach $part_referral
  if ( $cgi->param('agent_totals') and !$all_agent ) {
    my $row_agentnum = $agent->agentnum;
    # Include all components that are anywhere on this report
    my $component = join('', @components);
    my @row_params = (  'agentnum'              => $row_agentnum,
                        'cust_classnum'         => \@cust_classnums,
                        'use_override'          => $use_override,
                        'average_per_cust_pkg'  => $average_per_cust_pkg,
                        'distribute'            => $distribute,
                        'charges'               => $component,
                     );
    my $row_link = "$link;".
                   "agentnum=$row_agentnum;".
                   "distribute=$distribute;".
                   "charges=$component;";
    
    # package class filters
    if ( $cgi->param('class_agg_break') eq 'aggregate' ) {
      push @row_params, $class_param => \@classnums;
      $row_link .= "$class_param=$_;" foreach @classnums;
    }
    # refnum filters
    if ( $sel_part_referral ) {
      push @row_params, 'refnum' => $sel_part_referral->refnum;
      $row_link .= "refnum=;".$sel_part_referral->refnum;
    }
    # customer class filters
    $row_link .= "cust_classnum=$_;" foreach @cust_classnums;
    push @items, 'cust_bill_pkg';
    push @labels, mt('[_1] - Subtotal', $agent->agent);
    push @params, \@row_params;
    push @links, $row_link;
    push @colors, '000000'; # better idea?
    push @no_graph, 1;
  }
  $anum++;
} # foreach $agent
if ( $cgi->param('debug') == 1 ) {
  $FS::Report::Table::DEBUG = 1;
}
%init>