Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 5ef8b310

Von Kivitendo Admin vor etwa 11 Jahren hinzugefügt

  • ID 5ef8b31028dada9eff3c317fe92c0a9b05ea41a4
  • Vorgänger 880122f8
  • Nachfolger e112111e

Neue Verkaufsberichtvariante mit Umsatz-Sortierung

Es gibt einen neuen Menüeintrag "Verkaufsbericht Top", wo man nach den
gleichen Kategorien wie beim normalen Verkaufsbericht gruppieren kann,
aber wo man das Ergebnis nach Umsatz, Marge, Menge oder Gewicht
vorsortieren kann, was beim Standardverkaufsbericht nicht möglich war.
Dadurch kann man sich z.B. eine nach Umsatz sortierte Liste der Kunden
für einen Zeitraum anzeigen lassen. Es wird weiterhin nur auf Daten aus
"invoice" zurückgegriffen.
Es wird bei dieser Variante auf den gleichen Code zurückgegriffen,
allerdings wurde aus Gründen der Übersicht ein neuer Menüpunkt
eingeführt, in Zukunft könnte man dies vielleicht mit eigenen Reitern
besser machen.

Unterschiede anzeigen:

bin/mozilla/vk.pl
31 31
#
32 32
#======================================================================
33 33

  
34
# TODO
35
# if qty or weight is shown add unit
36

  
34 37
use POSIX qw(strftime);
35 38
use List::Util qw(sum first);
36 39

  
......
90 93
  $main::lxdebug->leave_sub();
91 94
}
92 95

  
96
sub search_invoice_top {
97
  $main::lxdebug->enter_sub();
98
  $main::auth->assert('general_ledger | invoice_edit');
99

  
100
  my $form     = $main::form;
101
  my %myconfig = %main::myconfig;
102
  my $locale   = $main::locale;
103

  
104
  my ($customer, $department);
105

  
106
  # setup customer selection
107
  $form->all_vc(\%myconfig, "customer", "AR");
108

  
109
  $form->{title}    = $locale->text('Sales Report Top');
110

  
111
  $form->get_lists("projects"        => { "key" => "ALL_PROJECTS", "all" => 1 },
112
                   "departments"     => "ALL_DEPARTMENTS",
113
                   "business_types"  => "ALL_BUSINESS_TYPES",
114
                   "salesmen"        => "ALL_SALESMEN",
115
                   'employees'       => 'ALL_EMPLOYEES',
116
                   'partsgroup'      => 'ALL_PARTSGROUPS',
117
                   "customers"       => "ALL_VC");
118
  $form->{CUSTOM_VARIABLES_IC}                  = CVar->get_configs('module' => 'IC');
119
  ($form->{CUSTOM_VARIABLES_FILTER_CODE_IC},
120
   $form->{CUSTOM_VARIABLES_INCLUSION_CODE_IC}) = CVar->render_search_options('variables'      => $form->{CUSTOM_VARIABLES_IC},
121
                                                                           'include_prefix' => 'l_',
122
                                                                           'include_value'  => 'Y');
123

  
124
  $form->{CUSTOM_VARIABLES_CT}                  = CVar->get_configs('module' => 'CT');
125
  ($form->{CUSTOM_VARIABLES_FILTER_CODE_CT},
126
   $form->{CUSTOM_VARIABLES_INCLUSION_CODE_CT}) = CVar->render_search_options('variables'      => $form->{CUSTOM_VARIABLES_CT},
127
                                                                           'include_prefix' => 'l_',
128
                                                                           'include_value'  => 'Y');
129
  $form->{vc_keys}   = sub { "$_[0]->{name}--$_[0]->{id}" };
130
  $form->{employee_labels} = sub { $_[0]->{"name"} || $_[0]->{"login"} };
131
  $form->{salesman_labels} = $form->{employee_labels};
132

  
133
  $form->header;
134
  print $form->parse_html_template('vk/search_invoice_top', { %myconfig });
135

  
136
  $main::lxdebug->leave_sub();
137
}
138

  
93 139
sub invoice_transactions {
94 140
  $main::lxdebug->enter_sub();
95 141

  
......
99 145
  my %myconfig = %main::myconfig;
100 146
  my $locale   = $main::locale;
101 147

  
148
  my @data_to_be_sorted;
149
  # debug mode for finding differences in Umsatz as calculated by database and perl
150
  # set to "Y" to turn on
151
  $form->{"l_sellpricelinetotal"} = "";
152

  
102 153
  my ($callback, $href, @columns);
103 154

  
155
  # sort_by_total mode
156
  if ( $form->{l_sort_by_total} ) {
157
    # uncheck Mainheadings
158
    # check both subheadings
159
    # set subsort = mainsort
160
    $form->{l_headers_mainsort}  = '';
161
    $form->{l_subtotal_mainsort} = "Y";
162
    $form->{l_headers_subsort} = ''; 
163
    $form->{l_subtotal_subsort} = "Y";
164
    $form->{mainsort} = $form->{topsortgroup};
165
    $form->{subsort} = $form->{mainsort};   # trigger subsort = mainsort
166
  };
167

  
104 168
  # can't currently be configured from report, empty line between main sortings
105 169
  my $addemptylines = 1;
106 170

  
......
139 203
  VK->invoice_transactions(\%myconfig, \%$form);
140 204

  
141 205

  
206

  
207

  
142 208
  if ( $form->{mainsort} eq 'month' or $form->{subsort} eq 'month' ) {
143 209

  
144 210
    # Data already comes out of SELECT statement in correct month order, but
......
155 221

  
156 222
  @columns =
157 223
    qw(description invnumber transdate customernumber customername partnumber partsgroup country business transdate qty parts_unit weight sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent employee salesman);
224
  push(@columns, "sellpricelinetotal") if $form->{"l_sellpricelinetotal"};
225
  
226
# sellpricelinetotal is qty*sellprice as calculated by database
158 227

  
159 228
  my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs_ic }, @{ $cvar_configs_ct };
160 229
  my @searchable_custom_variables  = grep { $_->{searchable} }  @{ $cvar_configs_ic }, @{ $cvar_configs_ct };
......
169 238
  my @hidden_variables  = (qw(l_headers_mainsort l_headers_subsort l_subtotal_mainsort l_subtotal_subsort l_total l_parts l_customername l_customernumber transdatefrom transdateto decimalplaces customer customername customer_id department partnumber partsgroup country business description project_id customernumber salesman employee salesman_id employee_id business_id partsgroup_id mainsort subsort),
170 239
      "$form->{db}number",
171 240
      map({ "cvar_$_->{name}" } @searchable_custom_variables),
172
      map { "l_$_" } @columns
241
      map { "l_$_" } @columns,
173 242
      );
243
  push(@hidden_variables, qw(topsortgroup topsorttype l_sort_by_total));  # hidden variables for top
244

  
174 245
  my @hidden_nondefault = grep({ $form->{$_} } @hidden_variables);
175 246
  # Variablen werden dann als Hidden Variable mitgegeben, z.B.
176 247
  # <input type="hidden" name="report_generator_hidden_transdateto" value="21.05.2010">
......
200 271
    'marge_percent'           => { 'text' => $locale->text('Sales margin %'), },
201 272
    'customernumber'          => { 'text' => $locale->text('Customer Number'), },
202 273
    'customername'            => { 'text' => $locale->text('Customer Name'), },
274
    'sellpricelinetotal'      => { 'text' => $locale->text('sellpricelinetotal'), }, # debug control
203 275
# add 3 more column_defs so we have a translation for top_info_text
204 276
    'customer'                => { 'text' => $locale->text('Customer'), },
205 277
    'part'                    => { 'text' => $locale->text('Part'), },
......
207 279
    %column_defs_cvars,
208 280
  );
209 281

  
210
  map { $column_defs{$_}->{visible} = $form->{"l_$_"} eq 'Y' } @columns;
282
  if ( not defined $form->{"l_parts"} ) {
283
    # the columns for sellprice, lastcost and marge_percent will be averages in subtotal and total lines
284
    map { $column_defs{$_}->{text} = $locale->text('Average symbol') . " " . $column_defs{$_}->{text} } qw(sellprice lastcost marge_percent);
285
  };
211 286

  
212
  my %column_alignment = map { $_ => 'right' } qw(lastcost sellprice sellprice_total lastcost_total parts_unit discount marge_total marge_percent qty weight);
287
  map { $column_defs{$_}->{visible} = $form->{"l_$_"} eq 'Y' } @columns;
213 288

  
289
  my %column_alignment = map { $_ => 'right' } qw(lastcost sellprice sellprice_total lastcost_total parts_unit discount marge_total marge_percent qty weight sellpricelinetotal );
214 290

  
215 291
  # so now the check-box "Description" is only used as switch for part description in invoice-mode
216 292
  # always fill the column "Description" if we are in Zwischensummenmode
217
  $form->{"l_description"} = "Y" if not defined $form->{"l_parts"};;
293
  $form->{"l_description"} = "Y" if not defined $form->{"l_parts"};
294

  
218 295
  map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
219 296

  
220 297
  my @options;
......
240 317

  
241 318
  my $report = SL::ReportGenerator->new(\%myconfig, $form);
242 319

  
320
  if ( not $form->{l_sort_by_total} ) {
243 321
  $report->set_options('top_info_text'        => join("\n", $locale->text('Main sorting') . ' : ' . $column_defs{$form->{mainsort}}->{text} , $locale->text('Secondary sorting') . ' : ' . $column_defs{$form->{'subsort'}}->{text}, @options),
244 322
                       'output_format'        => 'HTML',
245 323
                       'title'                => $form->{title},
246 324
                       'attachment_basename'  => $locale->text('Sales Report') . strftime('_%Y%m%d', localtime time),
247 325
    );
326
  } else {
327
  $report->set_options('top_info_text'        => join("\n", $locale->text('Grouping') . ' : ' . $column_defs{$form->{topsortgroup}}->{text} , $locale->text('Sort By') . ' : ' . $column_defs{$form->{'topsorttype'}}->{text}, @options),
328
                       'output_format'        => 'HTML',
329
                       'title'                => $form->{title},
330
                       'attachment_basename'  => $locale->text('Sales Report') . strftime('_%Y%m%d', localtime time),
331
    );
332
  };
333

  
248 334
  $report->set_options_from_form();
249 335
  $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
250 336

  
......
253 339

  
254 340
  $report->set_export_options('invoice_transactions', @hidden_variables, qw(mainsort sortdir));
255 341

  
256
  $report->set_sort_indicator($form->{mainsort}, $form->{sortdir});
342
  $report->set_sort_indicator($form->{mainsort}, $form->{sortdir}) unless $form->{"l_sort_by_total"};
343
  
257 344

  
258 345
  CVar->add_custom_variables_to_report('module'         => 'CT',
259 346
      'trans_id_field' => 'customerid',
......
284 371
  # escape callback for href
285 372
  $callback = $form->escape($href);
286 373

  
287
  my @subtotal_columns = qw(qty weight sellprice sellprice_total lastcost lastcost_total marge_total marge_percent discount);
374
  my @subtotal_columns = qw(qty weight sellprice sellprice_total lastcost lastcost_total marge_total marge_percent discount sellpricelinetotal);
288 375
  # Total sum:
289 376
  # sum of sellprice_total, lastcost_total and marge_total
290 377
  # average of marge_percent
291
  my @total_columns = qw(sellprice_total lastcost_total marge_total marge_percent );
378
# absolutes: qty, weight, sellprice_total, lastcost_total, marge_total
379
# averages: sellprice, lastcost, marge_percent
380
  my @total_columns = qw(sellprice_total lastcost_total marge_total marge_percent sellpricelinetotal);
292 381

  
293 382
  my %totals     = map { $_ => 0 } @total_columns;
294 383
  my %subtotals1 = map { $_ => 0 } @subtotal_columns;
......
396 485
    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(marge_percent qty);
397 486
    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 3) } qw(weight);
398 487
    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, $form->{"decimalplaces"} )} qw(lastcost sellprice sellprice_total lastcost_total marge_total);
488
    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, $form->{"decimalplaces"} )} qw(sellpricelinetotal) if $form->{"l_sellpricelinetotal"};
399 489

  
400 490
    # Einzelzeilen nur zeigen wenn l_parts gesetzt ist, nützlich, wenn man nur
401 491
    # Subtotals und Totals sehen möchte
492
    # these lines are only added to report in individual mode
493
    
402 494
    if ($form->{l_parts}) {
403 495
      my %row = (
404 496
        map { ($_ => { data => $ar->{$_}, align => $column_alignment{$_} }) } @columns
......
414 506

  
415 507
    # hier wird bei l_subtotal nicht differenziert zwischen mainsort und subsort
416 508
    # macht man l_subtotal_mainsort aus wird l_subtotal_subsort auch nicht ausgeführt
509
    # create a subtotal line if we are at the last element or either the subsort or mainsort element has changed
417 510
    if (   ($form->{l_subtotal_mainsort} eq 'Y')
418 511
        && ($form->{l_subtotal_subsort}  eq 'Y')
419 512
        && (($idx == (scalar @{ $form->{AR} } - 1))   # last element always has a subtotal
......
421 514
          || ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} })
422 515
          )) {   # if value that is sorted by changes, print subtotal
423 516

  
424
      $report->add_data(create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, $form->{l_parts} ? 'listsubtotal' : undef, $ar->{ $form->{'subsort'} }));
425
      $report->add_data({ %empty_row }) if $form->{l_parts} and $addemptylines;
426
    }
517

  
518
      # stick subtotal_row_invoice in temporary variable
519
      # if TOP mode store it in @data_to_be_sorted so we can sort the lines after all lines have been added
520
      # otherwise just add to $report to be shown in defualt
521
      my $tmpobject = create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, $form->{l_parts} ? 'listsubtotal' : undef, $ar->{ $form->{'subsort'} }); 
522
      if ( $form->{l_sort_by_total} and not $form->{l_parts} ) {
523
        # add subtotal data to temporary array that can later be sorted
524
        push(@data_to_be_sorted, $tmpobject);
525
      } else {
526
        $report->add_data( $tmpobject);
527
      };
528
     $report->add_data({ %empty_row }) if $form->{l_parts} and $addemptylines;
529
   
530
    };
427 531

  
428 532
    # if last mainsort is reached or mainsort has changed, add mainsort subtotal and empty row
429 533
    if (   ($form->{l_subtotal_mainsort} eq 'Y')
......
440 544

  
441 545
    $idx++;
442 546
  }
547

  
548

  
549
  if ( $form->{l_sort_by_total} ) {
550
    # filter allowed parameters for sorttype
551
    my @allowed_fields = qw(sellprice_total marge_total qty weight);
552
    my ($sorttype) = grep { /^$form->{topsorttype}$/ } @allowed_fields;
553
    die "illegal parameter for topsorttype" unless $sorttype;
554
  
555
    # add marker to column being sorted
556
    $report->set_sort_indicator($sorttype);
557
  
558
    # add subtotal lines to report in numerical order of sorttype
559
    @data_to_be_sorted = reverse sort { $a->{$sorttype}{unformatted} <=> $b->{$sorttype}{unformatted} } @data_to_be_sorted;
560
    foreach( @data_to_be_sorted ) {
561
      # to limit output, e.g. top 100, one could add a counter here
562
      # that only adds a certain number of entries
563
      # the total at the end would still be over all entries though 
564
      $report->add_data( $_ );
565
    };
566
  };
567

  
443 568
  if ( $form->{l_total} eq "Y" ) {
444 569
    $report->add_separator();
445 570
    $report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal', 'l_total'))
446 571
  };
447

  
572
  
448 573
  $report->generate_with_headers();
574

  
449 575
  $main::lxdebug->leave_sub();
450 576
}
451 577

  
......
470 596
    $row->{description}->{data} = $locale->text('Total') . ' ' . $name;
471 597
  };
472 598

  
599
  map { $row->{$_}->{unformatted} = $totals->{$_} } qw(sellprice_total lastcost_total marge_total qty weight);
473 600
  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } qw(marge_total marge_percent qty);
474 601
  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 3) } qw(weight);
475
  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, $form->{decimalplaces}) } qw(lastcost sellprice sellprice_total lastcost_total);
476

  
602
  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, $form->{decimalplaces}) } qw(lastcost sellprice sellprice_total lastcost_total sellpricelinetotal);
477 603

  
478 604
  map { $totals->{$_} = 0 } @{ $subtotal_columns };
479 605

  

Auch abrufbar als: Unified diff