Revision c820024d
Von Moritz Bunkus vor fast 2 Jahren hinzugefügt
- ID c820024dc915287ce62a7ea8397785e063b92584
- Vorgänger 1d181a39
SL/Controller/LiquidityProjection.pm | ||
---|---|---|
11 | 11 |
__PACKAGE__->run_before('check_auth'); |
12 | 12 |
|
13 | 13 |
use Rose::Object::MakeMethods::Generic ( |
14 |
scalar => [ qw(liquidity) ], |
|
15 |
'scalar --get_set_init' => [ qw(oe_report_columns_str) ], |
|
14 |
scalar => [ qw(liquidity) ], |
|
16 | 15 |
); |
17 | 16 |
|
18 | 17 |
|
... | ... | |
36 | 35 |
$self->render('liquidity_projection/show', title => t8('Liquidity projection')); |
37 | 36 |
} |
38 | 37 |
|
38 |
sub action_list_orders { |
|
39 |
my ($self) = @_; |
|
40 |
|
|
41 |
my @orders = SL::LiquidityProjection->orders_for_time_period( |
|
42 |
after => $::form->{after} ? DateTime->from_kivitendo($::form->{after}) : undef, |
|
43 |
before => $::form->{before} ? DateTime->from_kivitendo($::form->{before}) : undef, |
|
44 |
); |
|
45 |
|
|
46 |
$self->render( |
|
47 |
'liquidity_projection/list_orders', |
|
48 |
title => t8('Sales Orders'), |
|
49 |
ORDERS => \@orders, |
|
50 |
); |
|
51 |
} |
|
52 |
|
|
39 | 53 |
# |
40 | 54 |
# filters |
41 | 55 |
# |
... | ... | |
53 | 67 |
|
54 | 68 |
my $reqdate = $params{reqdate}; |
55 | 69 |
my $months = $params{months} * 1; |
70 |
my $today = DateTime->today_local->truncate(to => 'month'); |
|
71 |
my %url_params; |
|
56 | 72 |
|
57 | 73 |
my $fields = ''; |
58 | 74 |
|
59 | 75 |
if ($reqdate eq 'old') { |
60 |
$fields .= '&reqdate_unset_or_old=Y';
|
|
76 |
$url_params{before} = $today->to_kivitendo;
|
|
61 | 77 |
|
62 | 78 |
} elsif ($reqdate eq 'future') { |
63 |
my @now = localtime; |
|
64 |
$fields .= '&reqdatefrom=' . $self->iso_to_display(SL::LiquidityProjection::_the_date($now[5] + 1900, $now[4] + 1 + $months) . '-01'); |
|
79 |
$url_params{after} = $today->add(months => $months)->to_kivitendo; |
|
65 | 80 |
|
66 | 81 |
} else { |
67 |
$reqdate =~ m/(\d+)-(\d+)/; |
|
68 |
$fields .= '&reqdatefrom=' . $self->iso_to_display($reqdate . '-01');
|
|
69 |
$fields .= '&reqdateto=' . $self->iso_to_display($reqdate . sprintf('-%02d', DateTime->last_day_of_month(year => $1, month => $2)->day));
|
|
70 |
|
|
82 |
$reqdate =~ m/(\d+)-(\d+)/;
|
|
83 |
my $date = DateTime->new_local(year => $1, month => $2, day => 1);
|
|
84 |
$url_params{after} = $date->to_kivitendo;
|
|
85 |
$url_params{before} = $date->add(months => 1)->to_kivitendo; |
|
71 | 86 |
} |
72 | 87 |
|
73 |
return "oe.pl?action=orders&type=sales_order&vc=customer&" . $self->oe_report_columns_str . $fields; |
|
74 |
} |
|
75 |
|
|
76 |
sub iso_to_display { |
|
77 |
my ($self, $date) = @_; |
|
78 |
|
|
79 |
$::locale->reformat_date({ dateformat => 'yyyy-mm-dd' }, $date, $::myconfig{dateformat}); |
|
88 |
return $self->url_for(action => 'list_orders', %url_params); |
|
80 | 89 |
} |
81 | 90 |
|
82 | 91 |
sub setup_show_action_bar { |
SL/LiquidityProjection.pm | ||
---|---|---|
300 | 300 |
: $date; |
301 | 301 |
} |
302 | 302 |
|
303 |
sub orders_for_time_period { |
|
304 |
my ($class, %params) = @_; |
|
305 |
|
|
306 |
my $dbh = SL::DB::Order->new->db->dbh; |
|
307 |
|
|
308 |
my @recurring_orders; |
|
309 |
|
|
310 |
# 1. Alle aktiven Konfigurationen für wiederkehrende Rechnungen auslesen. |
|
311 |
|
|
312 |
my $configs = SL::DB::Manager::PeriodicInvoicesConfig->get_all(where => [ active => 1 ]); |
|
313 |
|
|
314 |
my %calc_params; |
|
315 |
$calc_params{start_date} = $params{after}->clone if $params{after}; |
|
316 |
$calc_params{end_date} = $params{before}->clone->add(days => -1) if $params{before}; |
|
317 |
$calc_params{end_date} //= $calc_params{start_date}->clone->add(years => 1); |
|
318 |
|
|
319 |
foreach my $config (@{ $configs }) { |
|
320 |
my @dates = $config->calculate_invoice_dates(%calc_params); |
|
321 |
next unless @dates; |
|
322 |
|
|
323 |
my $order = SL::DB::Order->new(id => $config->oe_id)->load(with_objects => [ qw(customer employee) ]); |
|
324 |
$order->{is_recurring} = 1; |
|
325 |
|
|
326 |
push @recurring_orders, $order; |
|
327 |
} |
|
328 |
|
|
329 |
my @where = ( |
|
330 |
'!customer_id' => undef, |
|
331 |
or => [ quotation => undef, quotation => 0, ], |
|
332 |
or => [ closed => undef, closed => 0, ], |
|
333 |
); |
|
334 |
push @where, (reqdate => { ge => $params{after}->clone }) if $params{after}; |
|
335 |
push @where, (reqdate => { lt => $params{before}->clone }) if $params{before}; |
|
336 |
push @where, '!id' => [ map { $_->id } @recurring_orders ] if @recurring_orders; |
|
337 |
|
|
338 |
# 1. Auslesen aller offenen Aufträge, deren Lieferdatum im |
|
339 |
# gewünschten Bereich liegt |
|
340 |
my $regular_orders = SL::DB::Manager::Order->get_all( |
|
341 |
where => \@where, |
|
342 |
with_objects => [ qw(customer employee) ], |
|
343 |
); |
|
344 |
|
|
345 |
return sort { |
|
346 |
($a->transdate <=> $b->transdate) |
|
347 |
|| ($a->reqdate <=> $b->reqdate) |
|
348 |
|| (lc($a->customer->name) cmp lc($b->customer->name)) |
|
349 |
} (@recurring_orders, @{ $regular_orders }); |
|
350 |
} |
|
351 |
|
|
303 | 352 |
1; |
locale/de/all | ||
---|---|---|
3020 | 3020 |
'Recorded Tax' => 'Gespeicherte Steuern', |
3021 | 3021 |
'Recorded taxkey' => 'Gespeicherter Steuerschlüssel', |
3022 | 3022 |
'Records' => 'Belege', |
3023 |
'Recurring' => 'Wiederkehrend', |
|
3023 | 3024 |
'Reduced Master Data' => 'Abschlag', |
3024 | 3025 |
'Reference' => 'Referenz', |
3025 | 3026 |
'Reference / Invoice Number' => 'Referenz / Rechnungsnummer', |
... | ... | |
4064 | 4065 |
'There are no entries that match the filter.' => 'Es gibt keine Einträge, auf die der Filter zutrifft.', |
4065 | 4066 |
'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.', |
4066 | 4067 |
'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enthält momentan keine Einträge.', |
4068 |
'There are no orders for the selected time period.' => 'Es gibt für den ausgewählten Zeitraum keine Aufträge.', |
|
4067 | 4069 |
'There are no record templates yet.' => 'Es gibt noch keine Belegvorlagen.', |
4068 | 4070 |
'There are parts with no reclamation reason at position:' => 'Es git Artikel mit keinem Reklamationsgrund an Position:', |
4069 | 4071 |
'There are several options you can handle this problem, please select one:' => 'Bitte wählen Sie eine der folgenden Optionen, um mit dem Problem umzugehen:', |
templates/design40_webpages/liquidity_projection/list_orders.html | ||
---|---|---|
1 |
[%- USE LxERP -%][%- USE HTML -%][%- USE P -%] |
|
2 |
|
|
3 |
<h1>[% HTML.escape(title) %]</h1> |
|
4 |
|
|
5 |
[% IF !ORDERS.size %] |
|
6 |
<p>[% LxERP.t8("There are no orders for the selected time period.") %]</p> |
|
7 |
|
|
8 |
[% ELSE %] |
|
9 |
|
|
10 |
<table class="tbl-list"> |
|
11 |
<thead> |
|
12 |
<tr class="listheading"> |
|
13 |
<th class="right">[% LxERP.t8("Date") %]</th> |
|
14 |
<th class="right">[% LxERP.t8("Delivery Date") %]</th> |
|
15 |
<th class="right">[% LxERP.t8("Order") %]</th> |
|
16 |
<th class="right">[% LxERP.t8("Customer Order Number") %]</th> |
|
17 |
<th>[% LxERP.t8("Customer") %]</th> |
|
18 |
<th class="right">[% LxERP.t8("Total") %]</th> |
|
19 |
<th class="right">[% LxERP.t8("Net amount") %]</th> |
|
20 |
<th>[% LxERP.t8("Employee") %]</th> |
|
21 |
<th>[% LxERP.t8("Transaction description") %]</th> |
|
22 |
<th>[% LxERP.t8("Recurring") %]</th> |
|
23 |
</tr> |
|
24 |
</thead> |
|
25 |
|
|
26 |
<tbody> |
|
27 |
[% FOREACH order = ORDERS %] |
|
28 |
<tr> |
|
29 |
<td class="date">[% HTML.escape(order.transdate.to_kivitendo) %]</td> |
|
30 |
<td class="date">[% HTML.escape(order.reqdate.to_kivitendo) %]</td> |
|
31 |
<td class="numeric">[% P.order.sales_order(order) %]</td> |
|
32 |
<td class="numeric">[% HTML.escape(order.cusordnumber) %]</td> |
|
33 |
<td>[% P.customer_vendor.customer(order.customer) %]</td> |
|
34 |
<td class="numeric">[% HTML.escape(LxERP.format_amount(order.amount, 2)) %]</td> |
|
35 |
<td class="numeric">[% HTML.escape(LxERP.format_amount(order.netamount, 2)) %]</td> |
|
36 |
<td>[% HTML.escape(order.employee.safe_name) %]</td> |
|
37 |
<td>[% HTML.escape(order.transaction_description) %]</td> |
|
38 |
<td>[% IF order.is_recurring %][% LxERP.t8("yes") %][% ELSE %][% LxERP.t8("no") %][% END %]</td> |
|
39 |
</tr> |
|
40 |
[% END %] |
|
41 |
</tbody> |
|
42 |
</table> |
|
43 |
[% END %] |
templates/webpages/liquidity_projection/list_orders.html | ||
---|---|---|
1 |
[%- USE LxERP -%][%- USE HTML -%][%- USE P -%] |
|
2 |
|
|
3 |
<h1>[% HTML.escape(title) %]</h1> |
|
4 |
|
|
5 |
[% IF !ORDERS.size %] |
|
6 |
<p>[% LxERP.t8("There are no orders for the selected time period.") %]</p> |
|
7 |
|
|
8 |
[% ELSE %] |
|
9 |
|
|
10 |
<table style="width: 100%"> |
|
11 |
<thead> |
|
12 |
<tr class="listheading"> |
|
13 |
<th align="right">[% LxERP.t8("Date") %]</th> |
|
14 |
<th align="right">[% LxERP.t8("Delivery Date") %]</th> |
|
15 |
<th align="right">[% LxERP.t8("Order") %]</th> |
|
16 |
<th align="right">[% LxERP.t8("Customer Order Number") %]</th> |
|
17 |
<th>[% LxERP.t8("Customer") %]</th> |
|
18 |
<th align="right">[% LxERP.t8("Total") %]</th> |
|
19 |
<th align="right">[% LxERP.t8("Net amount") %]</th> |
|
20 |
<th>[% LxERP.t8("Employee") %]</th> |
|
21 |
<th>[% LxERP.t8("Transaction description") %]</th> |
|
22 |
<th>[% LxERP.t8("Recurring") %]</th> |
|
23 |
</tr> |
|
24 |
</thead> |
|
25 |
|
|
26 |
<tbody> |
|
27 |
[% FOREACH order = ORDERS %] |
|
28 |
<tr class="listrow"> |
|
29 |
<td align="right">[% HTML.escape(order.transdate.to_kivitendo) %]</td> |
|
30 |
<td align="right">[% HTML.escape(order.reqdate.to_kivitendo) %]</td> |
|
31 |
<td align="right">[% P.order.sales_order(order) %]</td> |
|
32 |
<td align="right">[% HTML.escape(order.cusordnumber) %]</td> |
|
33 |
<td>[% P.customer_vendor.customer(order.customer) %]</td> |
|
34 |
<td align="right">[% HTML.escape(LxERP.format_amount(order.amount, 2)) %]</td> |
|
35 |
<td align="right">[% HTML.escape(LxERP.format_amount(order.netamount, 2)) %]</td> |
|
36 |
<td>[% HTML.escape(order.employee.safe_name) %]</td> |
|
37 |
<td>[% HTML.escape(order.transaction_description) %]</td> |
|
38 |
<td>[% IF order.is_recurring %][% LxERP.t8("yes") %][% ELSE %][% LxERP.t8("no") %][% END %]</td> |
|
39 |
</tr> |
|
40 |
[% END %] |
|
41 |
</tbody> |
|
42 |
</table> |
|
43 |
[% END %] |
Auch abrufbar als: Unified diff
Liquiditätsübersicht: Auftragsliste gefixt
Die Links im Tabellenfuß hatten bisher auf die normale Auftragssuche
verwiesen. Problem war aber, dass dabei schlicht nicht exakt
diejenigen Aufträge angezeigt wurden, die für die Liquiditätsübersicht
relevant waren: teils zu viele, teils zu wenige (z.B. nicht diejenigen
der wiederkehrenden Rechnungen).
Die neue Liste ist eine eigene Funktion des
Liquiditätsübersichts-Controllers, die explizit diejenigen Belege
heraussucht, die für die Berechnung herangezogen werden.