Revision a521b29b
Von G. Richardson vor mehr als 12 Jahren hinzugefügt
bin/mozilla/vk.pl | ||
---|---|---|
46 | 46 |
|
47 | 47 |
use strict; |
48 | 48 |
|
49 |
|
|
50 | 49 |
sub search_invoice { |
51 | 50 |
$main::lxdebug->enter_sub(); |
52 | 51 |
$main::auth->assert('general_ledger | invoice_edit'); |
... | ... | |
63 | 62 |
$form->{title} = $locale->text('Sales Report'); |
64 | 63 |
$form->{jsscript} = 1; |
65 | 64 |
|
66 |
$form->get_lists("projects" => { "key" => "ALL_PROJECTS", "all" => 1 }, |
|
67 |
"departments" => "ALL_DEPARTMENTS", |
|
68 |
"customers" => "ALL_VC"); |
|
69 |
|
|
65 |
$form->get_lists("projects" => { "key" => "ALL_PROJECTS", "all" => 1 }, |
|
66 |
"departments" => "ALL_DEPARTMENTS", |
|
67 |
"business_types" => "ALL_BUSINESS_TYPES", |
|
68 |
"salesmen" => "ALL_SALESMEN", |
|
69 |
'employees' => 'ALL_EMPLOYEES', |
|
70 |
'partsgroup' => 'ALL_PARTSGROUPS', |
|
71 |
"customers" => "ALL_VC"); |
|
72 |
$form->{CUSTOM_VARIABLES_IC} = CVar->get_configs('module' => 'IC'); |
|
73 |
($form->{CUSTOM_VARIABLES_FILTER_CODE_IC}, |
|
74 |
$form->{CUSTOM_VARIABLES_INCLUSION_CODE_IC}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES_IC}, |
|
75 |
'include_prefix' => 'l_', |
|
76 |
'include_value' => 'Y'); |
|
77 |
|
|
78 |
$form->{CUSTOM_VARIABLES_CT} = CVar->get_configs('module' => 'CT'); |
|
79 |
($form->{CUSTOM_VARIABLES_FILTER_CODE_CT}, |
|
80 |
$form->{CUSTOM_VARIABLES_INCLUSION_CODE_CT}) = CVar->render_search_options('variables' => $form->{CUSTOM_VARIABLES_CT}, |
|
81 |
'include_prefix' => 'l_', |
|
82 |
'include_value' => 'Y'); |
|
70 | 83 |
$form->{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" }; |
84 |
$form->{employee_labels} = sub { $_[0]->{"name"} || $_[0]->{"login"} }; |
|
85 |
$form->{salesman_labels} = $form->{employee_labels}; |
|
71 | 86 |
|
72 | 87 |
$form->header; |
73 | 88 |
print $form->parse_html_template('vk/search_invoice', { %myconfig }); |
... | ... | |
86 | 101 |
|
87 | 102 |
my ($callback, $href, @columns); |
88 | 103 |
|
104 |
# can't currently be configured from report, empty line between main sortings |
|
105 |
my $addemptylines = '1'; |
|
106 |
|
|
89 | 107 |
if ( $form->{customer} =~ /--/ ) { |
90 | 108 |
# Felddaten kommen aus Dropdownbox |
91 | 109 |
($form->{customername}, $form->{customer_id}) = split(/--/, $form->{customer}); |
... | ... | |
108 | 126 |
# decimalplaces überprüfen oder auf Default 2 setzen |
109 | 127 |
$form->{decimalplaces} = 2 unless $form->{decimalplaces} > 0 && $form->{decimalplaces} < 6; |
110 | 128 |
|
129 |
my $cvar_configs_ct = CVar->get_configs('module' => 'CT'); |
|
130 |
my $cvar_configs_ic = CVar->get_configs('module' => 'IC'); |
|
131 |
|
|
111 | 132 |
# report_generator_set_default_sort('transdate', 1); |
112 | 133 |
|
113 | 134 |
VK->invoice_transactions(\%myconfig, \%$form); |
114 | 135 |
|
115 |
# anhand von radio button die Sortierreihenfolge festlegen |
|
116 |
if ($form->{sortby} eq 'artikelsort') { |
|
117 |
$form->{'mainsort'} = 'parts_id'; |
|
118 |
$form->{'subsort'} = 'name'; |
|
119 |
} else { |
|
120 |
$form->{'mainsort'} = 'name'; |
|
121 |
$form->{'subsort'} = 'parts_id'; |
|
136 |
|
|
137 |
if ( $form->{mainsort} eq 'month' or $form->{subsort} eq 'month' ) { |
|
138 |
|
|
139 |
# Data already comes out of SELECT statement in correct month order, but |
|
140 |
# remove whitespaces (month names are padded) and translate them as early |
|
141 |
# as possible |
|
142 |
|
|
143 |
foreach (@{ $form->{AR} }) { |
|
144 |
$_->{month} =~ s/\s//g; |
|
145 |
$_->{month} = $locale->text($_->{month}); |
|
146 |
}; |
|
122 | 147 |
}; |
123 | 148 |
|
124 | 149 |
$form->{title} = $locale->text('Sales Report'); |
125 | 150 |
|
126 | 151 |
@columns = |
127 |
qw(description invnumber transdate customernumber partnumber transdate qty unit sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent); |
|
152 |
qw(description invnumber transdate customernumber customername partnumber partsgroup country business transdate qty unit sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent employee salesman); |
|
153 |
|
|
154 |
my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs_ic }, @{ $cvar_configs_ct }; |
|
155 |
my @searchable_custom_variables = grep { $_->{searchable} } @{ $cvar_configs_ic }, @{ $cvar_configs_ct }; |
|
156 |
my %column_defs_cvars = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables; |
|
157 |
|
|
158 |
push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables; |
|
159 |
|
|
128 | 160 |
|
129 | 161 |
# hidden variables für pdf/csv export übergeben |
130 | 162 |
# einmal mit l_ um zu bestimmen welche Spalten ausgegeben werden sollen |
131 | 163 |
# einmal optionen für die Überschrift (z.B. transdatefrom, partnumber, ...) |
132 |
my @hidden_variables = (qw(l_headers l_subtotal l_total l_customernumber transdatefrom transdateto decimalplaces customer customername customer_id department partnumber description project_id customernumber), "$form->{db}number", map { "l_$_" } @columns); |
|
164 |
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), |
|
165 |
"$form->{db}number", |
|
166 |
map({ "cvar_$_->{name}" } @searchable_custom_variables), |
|
167 |
map { "l_$_" } @columns |
|
168 |
); |
|
133 | 169 |
my @hidden_nondefault = grep({ $form->{$_} } @hidden_variables); |
134 | 170 |
# Variablen werden dann als Hidden Variable mitgegeben, z.B. |
135 | 171 |
# <input type="hidden" name="report_generator_hidden_transdateto" value="21.05.2010"> |
... | ... | |
140 | 176 |
my %column_defs = ( |
141 | 177 |
'description' => { 'text' => $locale->text('Description'), }, |
142 | 178 |
'partnumber' => { 'text' => $locale->text('Part Number'), }, |
179 |
'partsgroup' => { 'text' => $locale->text('Group'), }, |
|
180 |
'country' => { 'text' => $locale->text('Country'), }, |
|
181 |
'business' => { 'text' => $locale->text('Customer type'), }, |
|
182 |
'employee' => { 'text' => $locale->text('Employee'), }, |
|
183 |
'salesman' => { 'text' => $locale->text('Salesperson'), }, |
|
143 | 184 |
'invnumber' => { 'text' => $locale->text('Invoice Number'), }, |
144 | 185 |
'transdate' => { 'text' => $locale->text('Invoice Date'), }, |
145 | 186 |
'qty' => { 'text' => $locale->text('Quantity'), }, |
... | ... | |
152 | 193 |
'marge_total' => { 'text' => $locale->text('Sales margin'), }, |
153 | 194 |
'marge_percent' => { 'text' => $locale->text('Sales margin %'), }, |
154 | 195 |
'customernumber' => { 'text' => $locale->text('Customer Number'), }, |
196 |
'customername' => { 'text' => $locale->text('Customer Name'), }, |
|
197 |
# add 3 more column_defs so we have a translation for top_info_text |
|
198 |
'customer' => { 'text' => $locale->text('Customer'), }, |
|
199 |
'part' => { 'text' => $locale->text('Part'), }, |
|
200 |
'month' => { 'text' => $locale->text('Month'), }, |
|
201 |
%column_defs_cvars, |
|
155 | 202 |
); |
156 | 203 |
|
204 |
map { $column_defs{$_}->{visible} = $form->{"l_$_"} eq 'Y' } @columns; |
|
205 |
|
|
157 | 206 |
my %column_alignment = map { $_ => 'right' } qw(lastcost sellprice sellprice_total lastcost_total unit discount marge_total marge_percent qty); |
158 | 207 |
|
159 |
$form->{"l_type"} = "Y"; |
|
208 |
|
|
209 |
# so now the check-box "Description" is only used as switch for part description in invoice-mode |
|
210 |
# always fill the column "Description" if we are in Zwischensummenmode |
|
211 |
if (not defined $form->{"l_parts"}) { |
|
212 |
$form->{"l_description"} = "Y"; |
|
213 |
}; |
|
160 | 214 |
map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns; |
161 | 215 |
|
162 |
|
|
163 | 216 |
my @options; |
217 |
|
|
164 | 218 |
if ($form->{description}) { |
165 | 219 |
push @options, $locale->text('Description') . " : $form->{description}"; |
166 | 220 |
} |
... | ... | |
170 | 224 |
if ($form->{customernumber}) { |
171 | 225 |
push @options, $locale->text('Customer Number') . " : $form->{customernumber}"; |
172 | 226 |
} |
227 |
# TODO: es wird nur id übergeben |
|
173 | 228 |
if ($form->{department}) { |
174 | 229 |
my ($department) = split /--/, $form->{department}; |
175 | 230 |
push @options, $locale->text('Department') . " : $department"; |
... | ... | |
183 | 238 |
if ($form->{partnumber}) { |
184 | 239 |
push @options, $locale->text('Part Number') . " : $form->{partnumber}"; |
185 | 240 |
} |
241 |
if ($form->{partsgroup_id}) { |
|
242 |
my $partsgroup = SL::DB::PartsGroup->new(id => $form->{partsgroup_id})->load; |
|
243 |
push @options, $locale->text('Group') . " : $partsgroup->{partsgroup}"; |
|
244 |
} |
|
245 |
if ($form->{country}) { |
|
246 |
push @options, $locale->text('Country') . " : $form->{country}"; |
|
247 |
} |
|
248 |
if ($form->{employee_id}) { |
|
249 |
my $employee = SL::DB::Employee->new(id => $form->{employee_id})->load; |
|
250 |
push @options, $locale->text('Employee') . ' : ' . $employee->name; |
|
251 |
} |
|
252 |
if ($form->{salesman_id}) { |
|
253 |
my $salesman = SL::DB::Employee->new(id => $form->{salesman_id})->load; |
|
254 |
push @options, $locale->text('Salesman') . ' : ' . $salesman->name; |
|
255 |
} |
|
256 |
if ($form->{business_id}) { |
|
257 |
my $business = SL::DB::Business->new(id => $form->{business_id})->load; |
|
258 |
push @options, $locale->text('Customer type') . ' : ' . $business->description; |
|
259 |
} |
|
186 | 260 |
if ($form->{ordnumber}) { |
187 | 261 |
push @options, $locale->text('Order Number') . " : $form->{ordnumber}"; |
188 | 262 |
} |
... | ... | |
201 | 275 |
|
202 | 276 |
my $report = SL::ReportGenerator->new(\%myconfig, $form); |
203 | 277 |
|
204 |
$report->set_options('top_info_text' => join("\n", @options), |
|
278 |
$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),
|
|
205 | 279 |
'output_format' => 'HTML', |
206 | 280 |
'title' => $form->{title}, |
207 | 281 |
'attachment_basename' => $locale->text('Sales Report') . strftime('_%Y%m%d', localtime time), |
... | ... | |
216 | 290 |
|
217 | 291 |
$report->set_sort_indicator($form->{mainsort}, $form->{sortdir}); |
218 | 292 |
|
293 |
CVar->add_custom_variables_to_report('module' => 'CT', |
|
294 |
'trans_id_field' => 'customerid', |
|
295 |
'configs' => $cvar_configs_ct, |
|
296 |
'column_defs' => \%column_defs, |
|
297 |
'data' => $form->{AR} |
|
298 |
); |
|
299 |
|
|
300 |
CVar->add_custom_variables_to_report('module' => 'IC', |
|
301 |
'trans_id_field' => 'parts_id', |
|
302 |
'configs' => $cvar_configs_ic, |
|
303 |
'column_defs' => \%column_defs, |
|
304 |
'data' => $form->{AR} |
|
305 |
); |
|
306 |
|
|
219 | 307 |
# add sort and escape callback, this one we use for the add sub |
220 | 308 |
$form->{callback} = $href .= "&sort=$form->{mainsort}"; |
221 | 309 |
|
... | ... | |
241 | 329 |
# discount was already accounted for in db sellprice |
242 | 330 |
$ar->{sellprice} = $ar->{sellprice} / $ar->{price_factor}; |
243 | 331 |
$ar->{lastcost} = $ar->{lastcost} / $ar->{price_factor}; |
244 |
$ar->{sellprice_total} = $ar->{qty} * ( $ar->{fxsellprice} * ( 1 - $ar->{discount} ) ) ;
|
|
332 |
$ar->{sellprice_total} = $ar->{qty} * $ar->{sellprice};
|
|
245 | 333 |
$ar->{lastcost_total} = $ar->{qty} * $ar->{lastcost}; |
246 | 334 |
# marge_percent wird neu berechnet, da Wert in invoice leer ist (Bug) |
247 |
$ar->{marge_percent} = $ar->{sellprice_total} ? (($ar->{sellprice_total}-$ar->{lastcost_total}) / $ar->{sellprice_total}) : 0; |
|
335 |
$ar->{marge_percent} = $ar->{sellprice_total} ? (($ar->{sellprice_total}-$ar->{lastcost_total}) / $ar->{sellprice_total} * 100) : 0;
|
|
248 | 336 |
# marge_total neu berechnen |
249 | 337 |
$ar->{marge_total} = $ar->{sellprice_total} ? $ar->{sellprice_total}-$ar->{lastcost_total} : 0; |
250 | 338 |
$ar->{discount} *= 100; # für Ausgabe formatieren, 10% stored as 0.1 in db |
251 | 339 |
|
252 | 340 |
# Anfangshauptüberschrift |
253 |
if ( $form->{l_headers} eq "Y" && ( $idx == 0 or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } )) { |
|
254 |
my $name; |
|
341 |
if ( $form->{l_headers_mainsort} eq "Y" && ( $idx == 0 or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } )) { |
|
255 | 342 |
my $headerrow; |
256 |
if ( $form->{mainsort} eq 'parts_id' ) { |
|
257 |
$headerrow->{description}->{data} = "$ar->{description}"; |
|
343 |
|
|
344 |
# use $emptyname for mainsort header if mainsort is empty |
|
345 |
if ( $ar->{$form->{'mainsort'}} ) { |
|
346 |
$headerrow->{description}->{data} = $ar->{$form->{'mainsort'}}; |
|
258 | 347 |
} else { |
259 |
$headerrow->{description}->{data} = "$ar->{name}";
|
|
348 |
$headerrow->{description}->{data} = $locale->text('empty');
|
|
260 | 349 |
}; |
350 |
|
|
261 | 351 |
$headerrow->{description}->{class} = "listmainsortheader"; |
262 | 352 |
my $headerrow_set = [ $headerrow ]; |
263 | 353 |
$report->add_data($headerrow_set); |
... | ... | |
275 | 365 |
or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } |
276 | 366 |
) { |
277 | 367 |
my $headerrow; |
278 |
my $name; |
|
279 |
if ( $form->{subsort} eq 'parts_id' ) {
|
|
280 |
$name = 'description';
|
|
281 |
$headerrow->{description}->{data} = "$ar->{$name}";
|
|
368 |
|
|
369 |
# if subsort name is defined, use that name in header, otherwise use $emptyname
|
|
370 |
if ( $ar->{$form->{'subsort'}} ) {
|
|
371 |
$headerrow->{description}->{data} = $ar->{$form->{'subsort'}};
|
|
282 | 372 |
} else { |
283 |
$name = 'name'; |
|
284 |
$headerrow->{description}->{data} = "$ar->{$name}"; |
|
373 |
$headerrow->{description}->{data} = $locale->text('empty'); |
|
285 | 374 |
}; |
286 | 375 |
$headerrow->{description}->{class} = "listsubsortheader"; |
287 | 376 |
my $headerrow_set = [ $headerrow ]; |
288 |
$report->add_data($headerrow_set) if $form->{l_headers} eq "Y"; |
|
377 |
# special case: subsort headers only makes (aesthetical) sense if we show individual parts |
|
378 |
$report->add_data($headerrow_set) if $form->{l_headers_subsort} eq "Y" and $form->{l_parts}; |
|
289 | 379 |
}; |
290 | 380 |
|
291 | 381 |
map { $subtotals1{$_} += $ar->{$_}; |
... | ... | |
318 | 408 |
}; |
319 | 409 |
|
320 | 410 |
# Ertrag prozentual in den Summen: (summe VK - summe Ertrag) / summe VK |
321 |
$subtotals1{marge_percent} = $subtotals1{sellprice_total} ? (($subtotals1{sellprice_total} - $subtotals1{lastcost_total}) / $subtotals1{sellprice_total}) : 0; |
|
322 |
$subtotals2{marge_percent} = $subtotals2{sellprice_total} ? (($subtotals2{sellprice_total} - $subtotals2{lastcost_total}) / $subtotals2{sellprice_total}) : 0; |
|
411 |
$subtotals1{marge_percent} = $subtotals1{sellprice_total} ? (($subtotals1{sellprice_total} - $subtotals1{lastcost_total}) / $subtotals1{sellprice_total}) * 100 : 0;
|
|
412 |
$subtotals2{marge_percent} = $subtotals2{sellprice_total} ? (($subtotals2{sellprice_total} - $subtotals2{lastcost_total}) / $subtotals2{sellprice_total}) *100 : 0;
|
|
323 | 413 |
|
324 | 414 |
# Ertrag prozentual: (Summe VK betrag - Summe EK betrag) / Summe VK betrag |
325 | 415 |
# wird laufend bei jeder Position neu berechnet |
326 |
$totals{marge_percent} = $totals{sellprice_total} ? ( ($totals{sellprice_total} - $totals{lastcost_total}) / $totals{sellprice_total} ) : 0; |
|
416 |
$totals{marge_percent} = $totals{sellprice_total} ? ( ($totals{sellprice_total} - $totals{lastcost_total}) / $totals{sellprice_total} ) * 100 : 0;
|
|
327 | 417 |
|
328 | 418 |
map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(marge_total marge_percent); |
329 | 419 |
map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, $form->{"decimalplaces"} )} qw(lastcost sellprice sellprice_total lastcost_total); |
... | ... | |
342 | 432 |
$row->{invnumber}->{link} = build_std_url("script=is.pl", 'action=edit') |
343 | 433 |
. "&id=" . E($ar->{id}) . "&callback=${callback}"; |
344 | 434 |
|
345 |
my $row_set = [ $row ]; |
|
435 |
# Einzelzeilen nur zeigen wenn l_parts gesetzt ist, nützlich, wenn man nur |
|
436 |
# Subtotals und Totals sehen möchte |
|
437 |
my $row_set = $form->{l_parts} ? [ $row ] : [ ]; |
|
346 | 438 |
|
347 |
if (($form->{l_subtotal} eq 'Y') |
|
439 |
# hier wird bei l_subtotal nicht differenziert zwischen mainsort und subsort |
|
440 |
# macht man l_subtotal_mainsort aus wird l_subtotal_subsort auch nicht ausgeführt |
|
441 |
if (($form->{l_subtotal_mainsort} eq 'Y') |
|
348 | 442 |
&& (($idx == (scalar @{ $form->{AR} } - 1)) # last element always has a subtotal |
349 | 443 |
|| ($ar->{ $form->{'subsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'subsort'} }) |
350 | 444 |
|| ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} }) |
351 | 445 |
)) { # if value that is sorted by changes, print subtotal |
352 |
my $name; |
|
353 |
if ( $form->{subsort} eq 'parts_id' ) { |
|
354 |
$name = 'description'; |
|
355 |
} else { |
|
356 |
$name = 'name'; |
|
357 |
}; |
|
358 | 446 |
|
359 |
if ($form->{l_subtotal} eq 'Y') { |
|
360 |
push @{ $row_set }, create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, 'listsubsortsubtotal', $ar->{$name}) ;
|
|
361 |
push @{ $row_set }, insert_empty_row(); |
|
447 |
if ($form->{l_subtotal_subsort} eq 'Y') {
|
|
448 |
push @{ $row_set }, create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, 'listsubsortsubtotal', $ar->{ $form->{'subsort'} }) ;
|
|
449 |
push @{ $row_set }, insert_empty_row() if $form->{l_parts} and $addemptylines;
|
|
362 | 450 |
}; |
363 | 451 |
} |
364 | 452 |
|
365 |
# if mainsort has changed, add mainsort subtotal and empty row |
|
366 |
if (($form->{l_subtotal} eq 'Y') |
|
453 |
# if last mainsort is reached or mainsort has changed, add mainsort subtotal and empty row
|
|
454 |
if (($form->{l_subtotal_mainsort} eq 'Y')
|
|
367 | 455 |
&& (($idx == (scalar @{ $form->{AR} } - 1)) # last element always has a subtotal |
368 | 456 |
|| ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} }) |
369 | 457 |
)) { # if value that is sorted by changes, print subtotal |
370 |
my $name; |
|
371 |
if ( $form->{mainsort} eq 'parts_id' ) { |
|
372 |
$name = 'description'; |
|
373 |
} else { |
|
374 |
$name = 'name'; |
|
375 |
}; |
|
376 |
if ($form->{l_subtotal} eq 'Y' ) { |
|
377 |
push @{ $row_set }, create_subtotal_row_invoice(\%subtotals1, \@columns, \%column_alignment, \@subtotal_columns, 'listmainsortsubtotal', $ar->{$name}); |
|
378 |
push @{ $row_set }, insert_empty_row(); |
|
458 |
if ($form->{l_subtotal_mainsort} eq 'Y' and $form->{mainsort} ne $form->{subsort} ) { |
|
459 |
# subtotal is overriden if mainsort and subsort are equal, don't print |
|
460 |
# subtotal line even if it is selected |
|
461 |
push @{ $row_set }, create_subtotal_row_invoice(\%subtotals1, \@columns, \%column_alignment, \@subtotal_columns, 'listmainsortsubtotal', $ar->{$form->{mainsort}}); |
|
462 |
push @{ $row_set }, insert_empty_row() if $addemptylines; # insert empty row after mainsort |
|
379 | 463 |
}; |
380 | 464 |
} |
381 | 465 |
|
... | ... | |
385 | 469 |
} |
386 | 470 |
if ( $form->{l_total} eq "Y" ) { |
387 | 471 |
$report->add_separator(); |
388 |
$report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal')) |
|
472 |
$report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal', 'l_total'))
|
|
389 | 473 |
}; |
390 | 474 |
|
391 | 475 |
$report->generate_with_headers(); |
... | ... | |
409 | 493 |
|
410 | 494 |
my $form = $main::form; |
411 | 495 |
my %myconfig = %main::myconfig; |
496 |
my $locale = $main::locale; |
|
412 | 497 |
|
413 | 498 |
my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } }; |
414 | 499 |
|
415 |
$row->{description}->{data} = "Summe " . $name; |
|
500 |
# set name as "empty" if no value is given, except if we are dealing with the |
|
501 |
# absolute total, then just write "Total sum" |
|
502 |
# here we assume that no name will be called 'l_total' |
|
503 |
$name = $locale->text('empty') unless $name; |
|
504 |
if ( $name eq 'l_total' ) { |
|
505 |
$row->{description}->{data} = $locale->text('Total sum'); |
|
506 |
} else { |
|
507 |
$row->{description}->{data} = $locale->text('Total') . ' ' . $name; |
|
508 |
}; |
|
416 | 509 |
|
417 | 510 |
map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } qw(marge_total marge_percent); |
418 | 511 |
map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 0) } qw(qty); |
Auch abrufbar als: Unified diff
Verkaufsberichtsortierung um Land, Warengruppen, Kundentyp, Verkäufer und Monat erweitert
Hauptsortierung und Untersortierung sind jetzt nicht mehr auf Ware und Kunde
begrenzt, sondern man kann eine Kombinationen erstellen aus:
Es kann jetzt auch nach benutzerdefinierten Variablen gefiltert werden.
Der Verkaufsbericht spaltet sich mit seinen Optionen langsam in zwei
unterschiedliche Bereiche auf, den Artikelmodus, wo die einzelnen Zeilen aus
invoice angezeigt werden, und den Rechnungsmodus, wo nur die Zeilen der
Zwischensummen und Summen angezeigt werden, und die Detailinformationen
aus invoice nur stören.
Default ist Rechnungsmodus, den Artikelmodus kann man per Häkchen auswählen.
Je nachdem auf welcher Ebene man sich befindet machen dann auch Informationen
wie "Durchschnittsverkaufspreis" keinen Sinn mehr.
Bei Zuordnungen wo die Sortierung keinen Wert hat (z.B. Sortierung nach Land,
aber beim Kunden ist kein Land hinterlegt), erscheint als Überschrift "leer",
und alle leeren Werte werden als eine Gruppe zusammengefasst.