Revision 2ea1a379
Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt
SL/Controller/LiquidityProjection.pm | ||
---|---|---|
1 |
package SL::Controller::LiquidityProjection; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use SL::Locale::String; |
|
8 |
use SL::LiquidityProjection; |
|
9 |
use SL::Util qw(_hashify); |
|
10 |
|
|
11 |
__PACKAGE__->run_before('check_auth'); |
|
12 |
|
|
13 |
use Rose::Object::MakeMethods::Generic ( |
|
14 |
scalar => [ qw(liquidity) ], |
|
15 |
'scalar --get_set_init' => [ qw(oe_report_columns_str) ], |
|
16 |
); |
|
17 |
|
|
18 |
|
|
19 |
# |
|
20 |
# actions |
|
21 |
# |
|
22 |
|
|
23 |
sub action_show { |
|
24 |
my ($self) = @_; |
|
25 |
|
|
26 |
$self->liquidity(SL::LiquidityProjection->new(%{ $::form->{params} })->create) if $::form->{params}; |
|
27 |
|
|
28 |
$::form->{params} ||= { |
|
29 |
months => 6, |
|
30 |
type => 1, |
|
31 |
salesman => 1, |
|
32 |
buchungsgruppe => 1, |
|
33 |
}; |
|
34 |
|
|
35 |
$self->render('liquidity_projection/show', title => t8('Liquidity projection')); |
|
36 |
} |
|
37 |
|
|
38 |
# |
|
39 |
# filters |
|
40 |
# |
|
41 |
|
|
42 |
sub check_auth { $::auth->assert('report') } |
|
43 |
sub init_oe_report_columns_str { join '&', map { "$_=Y" } qw(open delivered notdelivered l_ordnumber l_transdate l_reqdate l_name l_employee l_salesman l_netamount l_amount l_transaction_description) } |
|
44 |
|
|
45 |
# |
|
46 |
# helpers |
|
47 |
# |
|
48 |
|
|
49 |
sub link_to_old_orders { |
|
50 |
my $self = shift; |
|
51 |
my %params = _hashify(0, @_); |
|
52 |
|
|
53 |
my $reqdate = $params{reqdate}; |
|
54 |
my $months = $params{months} * 1; |
|
55 |
|
|
56 |
my $fields = ''; |
|
57 |
|
|
58 |
if ($reqdate eq 'old') { |
|
59 |
$fields .= '&reqdate_unset_or_old=Y'; |
|
60 |
|
|
61 |
} elsif ($reqdate eq 'future') { |
|
62 |
my @now = localtime; |
|
63 |
$fields .= '&reqdatefrom=' . $self->iso_to_display(SL::LiquidityProjection::_the_date($now[5] + 1900, $now[4] + 1 + $months) . '-01'); |
|
64 |
|
|
65 |
} else { |
|
66 |
$reqdate =~ m/(\d+)-(\d+)/; |
|
67 |
$fields .= '&reqdatefrom=' . $self->iso_to_display($reqdate . '-01'); |
|
68 |
$fields .= '&reqdateto=' . $self->iso_to_display($reqdate . sprintf('-%02d', DateTime->last_day_of_month(year => $1, month => $2)->day)); |
|
69 |
|
|
70 |
} |
|
71 |
|
|
72 |
return "oe.pl?action=orders&type=sales_order&vc=customer&" . $self->oe_report_columns_str . $fields; |
|
73 |
} |
|
74 |
|
|
75 |
sub iso_to_display { |
|
76 |
my ($self, $date) = @_; |
|
77 |
|
|
78 |
$::locale->reformat_date({ dateformat => 'yyyy-mm-dd' }, $date, $::myconfig{dateformat}); |
|
79 |
} |
|
80 |
|
|
81 |
1; |
SL/LiquidityProjection.pm | ||
---|---|---|
1 |
package SL::LiquidityProjection; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use List::MoreUtils qw(uniq); |
|
6 |
|
|
7 |
use SL::DBUtils; |
|
8 |
|
|
9 |
sub new { |
|
10 |
my $package = shift; |
|
11 |
my $self = bless {}, $package; |
|
12 |
|
|
13 |
my %params = @_; |
|
14 |
|
|
15 |
$self->{params} = \%params; |
|
16 |
|
|
17 |
my @now = localtime; |
|
18 |
my $now_year = $now[5] + 1900; |
|
19 |
my $now_month = $now[4] + 1; |
|
20 |
|
|
21 |
$self->{min_date} = _the_date($now_year, $now_month); |
|
22 |
$self->{max_date} = _the_date($now_year, $now_month + $params{months} - 1); |
|
23 |
|
|
24 |
$self; |
|
25 |
} |
|
26 |
|
|
27 |
# Algorithmus: |
|
28 |
# |
|
29 |
# Für den aktuellen Monat und alle x Folgemonate soll der geplante |
|
30 |
# Liquiditätszufluss aufgeschlüsselt werden. Der Zufluss berechnet |
|
31 |
# sich dabei aus: |
|
32 |
# |
|
33 |
# 1. Summe aller offenen Auträge |
|
34 |
# |
|
35 |
# 2. abzüglich aller zu diesen Aufträgen erstellten Rechnungen |
|
36 |
# (Teillieferungen/Teilrechnungen) |
|
37 |
# |
|
38 |
# 3. zuzüglich alle aktiven Wartungsverträge, die in dem jeweiligen |
|
39 |
# Monat ihre Saldierungsperiode haben, außer Wartungsverträgen, die |
|
40 |
# für den jeweiligen Monat bereits abgerechnet wurden. |
|
41 |
# |
|
42 |
# Diese Werte sollen zusätzlich optional nach Verkäufer(in) und nach |
|
43 |
# Buchungsgruppe aufgeschlüsselt werden. |
|
44 |
# |
|
45 |
# Diese Lösung geht deshalb immer über die Positionen der Belege |
|
46 |
# (wegen der Buchungsgruppe) und berechnet die Summen daraus manuell. |
|
47 |
# |
|
48 |
# Alle Aufträge, deren Lieferdatum leer ist, oder deren Lieferdatum |
|
49 |
# vor dem aktuellen Monat liegt, werden in einer Kategorie 'alt' |
|
50 |
# zusammengefasst. |
|
51 |
# |
|
52 |
# Alle Aufträge, deren Lieferdatum nach dem zu betrachtenden Zeitraum |
|
53 |
# (aktueller Monat + x Monate) liegen, werden in einer Kategorie |
|
54 |
# 'Zukunft' zusammengefasst. |
|
55 |
# |
|
56 |
# Insgesamt läuft es wie folgt ab: |
|
57 |
# |
|
58 |
# 1. Es wird das Datum aller periodisch erzeugten Rechnungen innerhalb |
|
59 |
# des Betrachtungszeitraumes herausgesucht. |
|
60 |
# |
|
61 |
# 2. Alle aktiven Wartungsvertragskonfigurationen werden |
|
62 |
# ausgelesen. Die Saldierungsmonate werden solange aufaddiert, wie der |
|
63 |
# dabei herauskommende Monat nicht nach dem zu betrachtenden Zeitraum |
|
64 |
# liegt. |
|
65 |
# |
|
66 |
# 3. Für jedes Saldierungsintervall, das innerhalb des |
|
67 |
# Betrachtungszeitraumes liegt, und für das es für den Monat noch |
|
68 |
# keine Rechnung gibt (siehe 1.), wird diese Konfiguration für den |
|
69 |
# Monat vorgemerkt. |
|
70 |
# |
|
71 |
# 4. Es werden für alle offenen Kundenaufträge die Positionen |
|
72 |
# ausgelesen und mit Verkäufer(in), Buchungsgruppe verknüpft. Aus |
|
73 |
# Menge, Einzelpreis und Zeilenrabatt wird die Zeilensumme berechnet. |
|
74 |
# |
|
75 |
# 5. Mit den Informationen aus 3. und 4. werden Datenstrukturen |
|
76 |
# initialisiert, die für die Gesamtsummen, für alle Verkäufer(innen), |
|
77 |
# für alle Buchungsgruppen, für alle Monate Werte enthalten. |
|
78 |
# |
|
79 |
# 6. Es wird über alle Einträge aus 4. iteriert. Die Zeilensummen |
|
80 |
# werden in den entsprechenden Datenstrukturen aus 5. addiert. |
|
81 |
# |
|
82 |
# 7. Es wird über alle Einträge aus 3. iteriert. Die Zeilensummen |
|
83 |
# werden in den entsprechenden Datenstrukturen aus 5. addiert. |
|
84 |
# |
|
85 |
# 8. Es werden alle Rechnungspositionen ausgelesen, bei denen die |
|
86 |
# Auftragsnummer einer der aus 5. ermittelten Aufträge entspricht. |
|
87 |
# |
|
88 |
# 9. Es wird über alle Einträge aus 8. iteriert. Die Zeilensummen |
|
89 |
# werden von den entsprechenden Datenstrukturen aus 5. abgezogen. Als |
|
90 |
# Datum wird dabei das Datum des zu der Rechnung gehörenden Auftrages |
|
91 |
# genommen. Als Buchungsgruppe wird die Buchungsgruppe der Zeile |
|
92 |
# genommen. Falls es passieren sollte, dass diese Buchungsgruppe in |
|
93 |
# den Aufträgen nie vorgekommen ist (sprich Rechnung enthält |
|
94 |
# Positionen, die im Auftrag nicht enthalten sind, und die komplett |
|
95 |
# andere Buchungsgruppen verwenden), so wird schlicht die allererste |
|
96 |
# in 4. gefundene Buchungsgruppe damit belastet. |
|
97 |
|
|
98 |
sub create { |
|
99 |
my ($self) = @_; |
|
100 |
my %params = %{ $self->{params} }; |
|
101 |
|
|
102 |
my $dbh = $params{dbh} || $::form->get_standard_dbh; |
|
103 |
my ($sth, $ref, $query); |
|
104 |
|
|
105 |
$params{months} ||= 6; |
|
106 |
|
|
107 |
# 1. Auslesen aller erzeugten periodischen Rechnungen im |
|
108 |
# Betrachtungszeitraum |
|
109 |
my $q_min_date = $dbh->quote($self->{min_date} . '-01'); |
|
110 |
$query = <<SQL; |
|
111 |
SELECT pi.config_id, to_char(pi.period_start_date, 'YYYY-MM') AS period_start_date |
|
112 |
FROM periodic_invoices pi |
|
113 |
LEFT JOIN periodic_invoices_configs pcfg ON (pi.config_id = pcfg.id) |
|
114 |
WHERE pcfg.active |
|
115 |
AND (pi.period_start_date >= to_date($q_min_date, 'YYYY-MM-DD')) |
|
116 |
SQL |
|
117 |
|
|
118 |
my %periodic_invoices; |
|
119 |
$sth = prepare_execute_query($::form, $dbh, $query); |
|
120 |
while ($ref = $sth->fetchrow_hashref) { |
|
121 |
$periodic_invoices{ $ref->{config_id} } ||= { }; |
|
122 |
$periodic_invoices{ $ref->{config_id} }->{ $ref->{period_start_date} } = 1; |
|
123 |
} |
|
124 |
$sth->finish; |
|
125 |
|
|
126 |
# 2. Auslesen aktiver Wartungsvertragskonfigurationen |
|
127 |
$query = <<SQL; |
|
128 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal, |
|
129 |
bg.description AS buchungsgruppe, |
|
130 |
CASE WHEN COALESCE(e.name, '') = '' THEN e.login ELSE e.name END AS salesman, |
|
131 |
pcfg.periodicity, pcfg.id AS config_id, |
|
132 |
EXTRACT(year FROM pcfg.start_date) AS start_year, EXTRACT(month FROM pcfg.start_date) AS start_month |
|
133 |
FROM orderitems oi |
|
134 |
LEFT JOIN oe ON (oi.trans_id = oe.id) |
|
135 |
LEFT JOIN periodic_invoices_configs pcfg ON (oi.trans_id = pcfg.oe_id) |
|
136 |
LEFT JOIN parts p ON (oi.parts_id = p.id) |
|
137 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id) |
|
138 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id) |
|
139 |
WHERE pcfg.active |
|
140 |
SQL |
|
141 |
|
|
142 |
# 3. Iterieren über Saldierungsintervalle, vormerken |
|
143 |
my %periodicities = ( 'm' => 1, 'q' => 3, 'y' => 12 ); |
|
144 |
my @scentries; |
|
145 |
$sth = prepare_execute_query($::form, $dbh, $query); |
|
146 |
while ($ref = $sth->fetchrow_hashref) { |
|
147 |
my ($year, $month) = ($ref->{start_year}, $ref->{start_month}); |
|
148 |
my $date; |
|
149 |
|
|
150 |
while (($date = _the_date($year, $month)) le $self->{max_date}) { |
|
151 |
if (($date ge $self->{min_date}) && (!$periodic_invoices{ $ref->{config_id} } || !$periodic_invoices{ $ref->{config_id} }->{$date})) { |
|
152 |
push @scentries, { buchungsgruppe => $ref->{buchungsgruppe}, |
|
153 |
salesman => $ref->{salesman}, |
|
154 |
linetotal => $ref->{linetotal}, |
|
155 |
date => $date, |
|
156 |
}; |
|
157 |
} |
|
158 |
|
|
159 |
($year, $month) = _fix_date($year, $month + ($periodicities{ $ref->{periodicity} } || 1)); |
|
160 |
} |
|
161 |
} |
|
162 |
$sth->finish; |
|
163 |
|
|
164 |
# 4. Auslesen offener Aufträge |
|
165 |
$query = <<SQL; |
|
166 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal, |
|
167 |
bg.description AS buchungsgruppe, |
|
168 |
CASE WHEN COALESCE(e.name, '') = '' THEN e.login ELSE e.name END AS salesman, |
|
169 |
oe.ordnumber, EXTRACT(month FROM oe.reqdate) AS month, EXTRACT(year FROM oe.reqdate) AS year |
|
170 |
FROM orderitems oi |
|
171 |
LEFT JOIN oe ON (oi.trans_id = oe.id) |
|
172 |
LEFT JOIN parts p ON (oi.parts_id = p.id) |
|
173 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id) |
|
174 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id) |
|
175 |
WHERE (oe.customer_id IS NOT NULL) |
|
176 |
AND NOT COALESCE(oe.quotation, FALSE) |
|
177 |
AND NOT COALESCE(oe.closed, FALSE) |
|
178 |
AND (oe.id NOT IN (SELECT oe_id FROM periodic_invoices_configs)) |
|
179 |
SQL |
|
180 |
|
|
181 |
# 5. Initialisierung der Datenstrukturen zum Speichern der |
|
182 |
# Ergebnisse |
|
183 |
my @entries = selectall_hashref_query($::form, $dbh, $query); |
|
184 |
my @salesmen = uniq map { $_->{salesman} } (@entries, @scentries); |
|
185 |
my @buchungsgruppen = uniq map { $_->{buchungsgruppe} } (@entries, @scentries); |
|
186 |
my @now = localtime; |
|
187 |
my @dates = map { $self->_date_for($now[5] + 1900, $now[4] + $_) } (0..$self->{params}->{months} + 1); |
|
188 |
my %dates_by_ordnumber = map { $_->{ordnumber} => $self->_date_for($_) } @entries; |
|
189 |
my %salesman_by_ordnumber = map { $_->{ordnumber} => $_->{salesman} } @entries; |
|
190 |
my %date_sorter = ( old => '0000-00', future => '9999-99' ); |
|
191 |
|
|
192 |
my $projection = { total => { map { $_ => 0 } @dates }, |
|
193 |
order => { map { $_ => 0 } @dates }, |
|
194 |
partial => { map { $_ => 0 } @dates }, |
|
195 |
support => { map { $_ => 0 } @dates }, |
|
196 |
salesman => { map { $_ => { map { $_ => 0 } @dates } } @salesmen }, |
|
197 |
buchungsgruppe => { map { $_ => { map { $_ => 0 } @dates } } @buchungsgruppen }, |
|
198 |
sorted => { month => [ sort { ($date_sorter{$a} || $a) cmp ($date_sorter{$b} || $b) } @dates ], |
|
199 |
salesman => [ sort { $a cmp $b } @salesmen ], |
|
200 |
buchungsgruppe => [ sort { $a cmp $b } @buchungsgruppen ], |
|
201 |
type => [ qw(order partial support) ], |
|
202 |
}, |
|
203 |
}; |
|
204 |
|
|
205 |
# 6. Aufsummieren der Auftragspositionen |
|
206 |
foreach $ref (@entries) { |
|
207 |
my $date = $self->_date_for($ref); |
|
208 |
|
|
209 |
$projection->{total}->{$date} += $ref->{linetotal}; |
|
210 |
$projection->{order}->{$date} += $ref->{linetotal}; |
|
211 |
$projection->{salesman}->{ $ref->{salesman} }->{$date} += $ref->{linetotal}; |
|
212 |
$projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} }->{$date} += $ref->{linetotal}; |
|
213 |
} |
|
214 |
|
|
215 |
# 7. Aufsummieren der Wartungsvertragspositionen |
|
216 |
foreach $ref (@scentries) { |
|
217 |
my $date = $ref->{date}; |
|
218 |
|
|
219 |
$projection->{total}->{$date} += $ref->{linetotal}; |
|
220 |
$projection->{support}->{$date} += $ref->{linetotal}; |
|
221 |
$projection->{salesman}->{ $ref->{salesman} }->{$date} += $ref->{linetotal}; |
|
222 |
$projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} }->{$date} += $ref->{linetotal}; |
|
223 |
} |
|
224 |
|
|
225 |
if (%dates_by_ordnumber) { |
|
226 |
# 8. Auslesen von Positionen von Teilrechnungen zu Aufträgen |
|
227 |
my $ordnumbers = join ', ', map { $dbh->quote($_) } keys %dates_by_ordnumber; |
|
228 |
$query = <<SQL; |
|
229 |
SELECT (i.qty * (1 - i.discount) * i.sellprice) AS linetotal, |
|
230 |
bg.description AS buchungsgruppe, |
|
231 |
ar.ordnumber |
|
232 |
FROM invoice i |
|
233 |
LEFT JOIN ar ON (i.trans_id = ar.id) |
|
234 |
LEFT JOIN parts p ON (i.parts_id = p.id) |
|
235 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id) |
|
236 |
WHERE (ar.ordnumber IN ($ordnumbers)) |
|
237 |
SQL |
|
238 |
|
|
239 |
@entries = selectall_hashref_query($::form, $dbh, $query); |
|
240 |
|
|
241 |
# 9. Abziehen der abgerechneten Positionen |
|
242 |
foreach $ref (@entries) { |
|
243 |
my $date = $dates_by_ordnumber{ $ref->{ordnumber} } || die; |
|
244 |
my $salesman = $salesman_by_ordnumber{ $ref->{ordnumber} } || die; |
|
245 |
my $buchungsgruppe = $projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} } ? $ref->{buchungsgruppe} : $buchungsgruppen[0]; |
|
246 |
|
|
247 |
$projection->{partial}->{$date} -= $ref->{linetotal}; |
|
248 |
$projection->{total}->{$date} -= $ref->{linetotal}; |
|
249 |
$projection->{salesman}->{$salesman}->{$date} -= $ref->{linetotal}; |
|
250 |
$projection->{buchungsgruppe}->{$buchungsgruppe}->{$date} -= $ref->{linetotal}; |
|
251 |
} |
|
252 |
} |
|
253 |
|
|
254 |
return $projection; |
|
255 |
} |
|
256 |
|
|
257 |
# Skaliert '$year' und '$month' so, dass 1 <= Monat <= 12 gilt. Zum |
|
258 |
# Einfachen Addieren gedacht, z.B. |
|
259 |
# |
|
260 |
# my ($new_year, $new_month) = _fix_date($old_year, $old_month + 6); |
|
261 |
|
|
262 |
sub _fix_date { |
|
263 |
my $year = shift; |
|
264 |
my $month = shift; |
|
265 |
|
|
266 |
$year += int(($month - 1) / 12); |
|
267 |
$month = (($month - 1) % 12 ) + 1; |
|
268 |
|
|
269 |
($year, $month); |
|
270 |
} |
|
271 |
|
|
272 |
# Formartiert Jahr & Monat wie benötigt. |
|
273 |
|
|
274 |
sub _the_date { |
|
275 |
sprintf '%04d-%02d', _fix_date(@_); |
|
276 |
} |
|
277 |
|
|
278 |
# Mappt Datum auf Kategorie. Ist das Datum leer, oder liegt es vor dem |
|
279 |
# Betrachtungszeitraum, so ist die Kategorie 'old'. Liegt das Datum |
|
280 |
# nach dem Betrachtungszeitraum, so ist die Kategorie |
|
281 |
# 'future'. Andernfalls ist sie das formartierte Datum selber. |
|
282 |
|
|
283 |
sub _date_for { |
|
284 |
my $self = shift; |
|
285 |
my $ref = ref $_[0] eq 'HASH' ? shift : { year => $_[0], month => $_[1] }; |
|
286 |
|
|
287 |
return 'old' if !$ref->{year} || !$ref->{month}; |
|
288 |
|
|
289 |
my $date = _the_date($ref->{year}, $ref->{month}); |
|
290 |
|
|
291 |
$date lt $self->{min_date} ? 'old' |
|
292 |
: $date gt $self->{max_date} ? 'future' |
|
293 |
: $date; |
|
294 |
} |
|
295 |
|
|
296 |
1; |
SL/OE.pm | ||
---|---|---|
244 | 244 |
$query .= qq| AND ${not} COALESCE(pcfg.active, 'f')|; |
245 | 245 |
} |
246 | 246 |
|
247 |
if ($form->{reqdate_unset_or_old}) { |
|
248 |
$query .= qq| AND ((o.reqdate IS NULL) OR (o.reqdate < date_trunc('month', current_date)))|; |
|
249 |
} |
|
250 |
|
|
247 | 251 |
if (($form->{order_probability_value} || '') ne '') { |
248 | 252 |
my $op = $form->{order_probability_value} eq 'le' ? '<=' : '>='; |
249 | 253 |
$query .= qq| AND (o.order_probability ${op} ?)|; |
bin/mozilla/oe.pl | ||
---|---|---|
883 | 883 |
push @hidden_variables, "l_subtotal", $form->{vc}, qw(l_closed l_notdelivered open closed delivered notdelivered ordnumber quonumber cusordnumber |
884 | 884 |
transaction_description transdatefrom transdateto type vc employee_id salesman_id |
885 | 885 |
reqdatefrom reqdateto projectnumber project_id periodic_invoices_active periodic_invoices_inactive |
886 |
business_id shippingpoint taxzone_id |
|
886 |
business_id shippingpoint taxzone_id reqdate_unset_or_old
|
|
887 | 887 |
order_probability_op order_probability_value expected_billing_date_from expected_billing_date_to); |
888 | 888 |
|
889 | 889 |
my @keys_for_url = grep { $form->{$_} } @hidden_variables; |
... | ... | |
969 | 969 |
push @options, $locale->text('Delivery Order created') if $form->{delivered}; |
970 | 970 |
push @options, $locale->text('Not delivered') if $form->{notdelivered}; |
971 | 971 |
push @options, $locale->text('Periodic invoices active') if $form->{periodic_invoices_active}; |
972 |
push @options, $locale->text('Reqdate not set or before current month') if $form->{reqdate_unset_or_old}; |
|
972 | 973 |
|
973 | 974 |
if ($form->{business_id}) { |
974 | 975 |
my $vc_type_label = $form->{vc} eq 'customer' ? $locale->text('Customer type') : $locale->text('Vendor type'); |
locale/de/all | ||
---|---|---|
325 | 325 |
'Basic Settings for the Requirement Spec Template' => 'Grundeinstellungen der Pflichtenheftvorlage', |
326 | 326 |
'Basic settings' => 'Grundeinstellungen', |
327 | 327 |
'Basic settings actions' => 'Aktionen zu Grundeinstellungen', |
328 |
'Basis of calculation' => 'Berechnungsgrundlage', |
|
328 | 329 |
'Batch Printing' => 'Druck', |
329 | 330 |
'Bcc' => 'Bcc', |
330 | 331 |
'Bcc E-mail' => 'BCC (E-Mail)', |
... | ... | |
365 | 366 |
'Both' => 'Beide', |
366 | 367 |
'Bottom' => 'Unten', |
367 | 368 |
'Bought' => 'Gekauft', |
369 |
'Break down by' => 'Aufschlüsseln nach', |
|
368 | 370 |
'Break up the update and contact a service provider.' => 'Diese Option bricht das Update ab. Bitte kontaktieren Sie Ihren Administrator oder beauftragen einen Dienstleister.', |
369 | 371 |
'Buchungsdatum' => 'Buchungsdatum', |
370 | 372 |
'Buchungsgruppe' => 'Buchungsgruppe', |
... | ... | |
1378 | 1380 |
'Link to' => 'Verknüpfen mit', |
1379 | 1381 |
'Link to the following project:' => 'Mit dem folgenden Projekt verknüpfen:', |
1380 | 1382 |
'Linked Records' => 'Verknüpfte Belege', |
1383 |
'Liquidity projection' => 'Liquiditätsübersicht', |
|
1381 | 1384 |
'List Accounts' => 'Konten anzeigen', |
1382 | 1385 |
'List Languages' => 'Sprachen anzeigen', |
1383 | 1386 |
'List Price' => 'Listenpreis', |
... | ... | |
1594 | 1597 |
'Number of bins' => 'Anzahl Lagerplätze', |
1595 | 1598 |
'Number of copies' => 'Anzahl Kopien', |
1596 | 1599 |
'Number of entries changed: #1' => 'Anzahl geänderter Einträge: #1', |
1600 |
'Number of months' => 'Anzahl Monate', |
|
1597 | 1601 |
'Number of new bins' => 'Anzahl neuer Lagerplätze', |
1598 | 1602 |
'Number pages' => 'Seiten nummerieren', |
1599 | 1603 |
'Number variables: \'PRECISION=n\' forces numbers to be shown with exactly n decimal places.' => 'Zahlenvariablen: Mit \'PRECISION=n\' erzwingt man, dass Zahlen mit n Nachkommastellen formatiert werden.', |
... | ... | |
1680 | 1684 |
'Part Number' => 'Artikelnummer', |
1681 | 1685 |
'Part Number missing!' => 'Artikelnummer fehlt!', |
1682 | 1686 |
'Part picker' => 'Artikelauswahl', |
1687 |
'Partial invoices' => 'Teilrechnungen', |
|
1683 | 1688 |
'Partnumber' => 'Artikelnummer', |
1684 | 1689 |
'Partnumber must not be set to empty!' => 'Die Artikelnummer darf nicht auf leer geändert werden.', |
1685 | 1690 |
'Partnumber not unique!' => 'Artikelnummer bereits vorhanden!', |
... | ... | |
1938 | 1943 |
'Representative' => 'Vertreter', |
1939 | 1944 |
'Representative for Customer' => 'Vertreter für Kunden', |
1940 | 1945 |
'Reqdate' => 'Liefertermin', |
1946 |
'Reqdate not set or before current month' => 'Lieferdatum nicht gesetzt oder vor aktuellem Monat', |
|
1941 | 1947 |
'Request Quotations' => 'Preisanfragen', |
1942 | 1948 |
'Request for Quotation' => 'Anfrage', |
1943 | 1949 |
'Request for Quotation Number' => 'Anfragenummer', |
... | ... | |
3001 | 3007 |
'not yet executed' => 'Noch nicht ausgeführt', |
3002 | 3008 |
'number' => 'Nummer', |
3003 | 3009 |
'oe.pl::search called with unknown type' => 'oe.pl::search mit unbekanntem Typ aufgerufen', |
3010 |
'old' => 'alt', |
|
3004 | 3011 |
'on the same day' => 'am selben Tag', |
3005 | 3012 |
'one-time execution' => 'einmalige Ausführung', |
3006 | 3013 |
'only OB Transactions' => 'nur EB-Buchungen', |
... | ... | |
3023 | 3030 |
'prev' => 'zurück', |
3024 | 3031 |
'print' => 'drucken', |
3025 | 3032 |
'proforma' => 'Proforma', |
3033 |
'prospective' => 'zukünftig', |
|
3026 | 3034 |
'purchase_delivery_order_list' => 'lieferscheinliste_einkauf', |
3027 | 3035 |
'purchase_order' => 'Auftrag', |
3028 | 3036 |
'purchase_order_list' => 'lieferantenauftragsliste', |
menus/erp.ini | ||
---|---|---|
450 | 450 |
module=controller.pl |
451 | 451 |
action=FinancialOverview/list |
452 | 452 |
|
453 |
[Reports--Liquidity projection] |
|
454 |
ACCESS=report |
|
455 |
module=controller.pl |
|
456 |
action=LiquidityProjection/show |
|
453 | 457 |
|
454 | 458 |
[Batch Printing] |
455 | 459 |
ACCESS=batch_printing |
templates/webpages/liquidity_projection/_filter.html | ||
---|---|---|
1 |
[%- USE LxERP -%][%- USE L -%] |
|
2 |
|
|
3 |
<form method="post" action="controller.pl"> |
|
4 |
[% L.hidden_tag('action', 'LiquidityProjection/show') %] |
|
5 |
|
|
6 |
<table border="0"> |
|
7 |
<tr> |
|
8 |
<th align="right">[% LxERP.t8("Number of months") %]</th> |
|
9 |
<td>[% L.input_tag("params.months", FORM.params.months, class="initial_focus") %]</td> |
|
10 |
</tr> |
|
11 |
|
|
12 |
<tr> |
|
13 |
<th align="right" valign="top">[% LxERP.t8("Break down by") %]</th> |
|
14 |
<td valign="top"> |
|
15 |
[% L.checkbox_tag("params.type", value=1, checked=FORM.params.type, label=LxERP.t8("Basis of calculation")) %] |
|
16 |
<br> |
|
17 |
[% L.checkbox_tag("params.salesman", value=1, checked=FORM.params.salesman, label=LxERP.t8("Salesman")) %] |
|
18 |
<br> |
|
19 |
[% L.checkbox_tag("params.buchungsgruppe", value=1, checked=FORM.params.buchungsgruppe, label=LxERP.t8("Buchungsgruppe")) %] |
|
20 |
</td> |
|
21 |
</tr> |
|
22 |
</table> |
|
23 |
|
|
24 |
<p> |
|
25 |
[% L.submit_tag("dummy", LxERP.t8("Show")) %] |
|
26 |
</p> |
|
27 |
</form> |
templates/webpages/liquidity_projection/_result.html | ||
---|---|---|
1 |
[%- USE HTML -%][%- USE LxERP -%] |
|
2 |
[%- SET name_col = FORM.params.salesman || FORM.params.buchungsgruppe || FORM.params.type %] |
|
3 |
|
|
4 |
<table border="0"> |
|
5 |
<tr> |
|
6 |
<th class="listheading">[% LxERP.t8("Type") %]</th> |
|
7 |
[%- IF name_col %] |
|
8 |
<th class="listheading">[% LxERP.t8("Name") %]</th> |
|
9 |
[%- END %] |
|
10 |
[%- FOREACH month = SELF.liquidity.sorted.month %] |
|
11 |
<th class="listheading" align="right">[%- IF month == 'old' %][% LxERP.t8("old") %][% ELSIF month == 'future' %][% LxERP.t8("prospective") %][% ELSE %][%- HTML.escape(month) %][% END %]</th> |
|
12 |
[%- END %] |
|
13 |
</tr> |
|
14 |
|
|
15 |
[% IF FORM.params.type %] |
|
16 |
[% FOREACH type = SELF.liquidity.sorted.type %] |
|
17 |
<tr class="listrow"> |
|
18 |
<td>[% IF loop.first %][% LxERP.t8("Basis of calculation") %][% END %]</td> |
|
19 |
<td> |
|
20 |
[% IF type == 'order' %][% LxERP.t8("Sales Orders") %] |
|
21 |
[% ELSIF type == 'partial' %][% LxERP.t8("Partial invoices") %] |
|
22 |
[% ELSE %][% LxERP.t8("Periodic Invoices") %] |
|
23 |
[% END %] |
|
24 |
</td> |
|
25 |
|
|
26 |
[%- FOREACH month = SELF.liquidity.sorted.month %] |
|
27 |
<td align="right">[% LxERP.format_amount(SELF.liquidity.$type.$month, 2) %]</td> |
|
28 |
[%- END %] |
|
29 |
</tr> |
|
30 |
[%- END %] |
|
31 |
[%- END %] |
|
32 |
|
|
33 |
[%- IF FORM.params.salesman %] |
|
34 |
[%- FOREACH salesman = SELF.liquidity.sorted.salesman %] |
|
35 |
<tr class="listrow"> |
|
36 |
<td>[% IF loop.first %][% LxERP.t8("Salesman") %][% END %]</td> |
|
37 |
<td>[%- HTML.escape(salesman) %]</td> |
|
38 |
|
|
39 |
[%- FOREACH month = SELF.liquidity.sorted.month %] |
|
40 |
<td align="right">[% LxERP.format_amount(SELF.liquidity.salesman.$salesman.$month, 2) %]</td> |
|
41 |
[%- END %] |
|
42 |
</tr> |
|
43 |
[%- END %] |
|
44 |
[%- END %] |
|
45 |
|
|
46 |
[%- IF FORM.params.buchungsgruppe %] |
|
47 |
[%- FOREACH buchungsgruppe = SELF.liquidity.sorted.buchungsgruppe %] |
|
48 |
<tr class="listrow"> |
|
49 |
<td>[% IF loop.first %][% LxERP.t8("Buchungsgruppe") %][% END %]</td> |
|
50 |
<td>[%- HTML.escape(buchungsgruppe) %]</td> |
|
51 |
|
|
52 |
[%- FOREACH month = SELF.liquidity.sorted.month %] |
|
53 |
<td align="right">[% LxERP.format_amount(SELF.liquidity.buchungsgruppe.$buchungsgruppe.$month, 2) %]</td> |
|
54 |
[%- END %] |
|
55 |
</tr> |
|
56 |
[%- END %] |
|
57 |
[%- END %] |
|
58 |
|
|
59 |
<tr class="listrow listtotal"> |
|
60 |
<td>[% LxERP.t8("Total") %]</td> |
|
61 |
[% IF name_col %]<td></td>[% END %] |
|
62 |
[%- FOREACH month = SELF.liquidity.sorted.month %] |
|
63 |
<td align="right"> |
|
64 |
[% IF SELF.liquidity.total.$month > 0 %] |
|
65 |
<a href="[% HTML.escape(SELF.link_to_old_orders(reqdate=month, months=params.months)) %]"> |
|
66 |
[% END %] |
|
67 |
[% LxERP.format_amount(SELF.liquidity.total.$month, 2) %] |
|
68 |
[% IF SELF.liquidity.total.$month > 0 %] |
|
69 |
</a> |
|
70 |
[% END %] |
|
71 |
</td> |
|
72 |
[%- END %] |
|
73 |
</tr> |
|
74 |
</table> |
templates/webpages/liquidity_projection/show.html | ||
---|---|---|
1 |
[% USE HTML %][% USE LxERP %][%- USE L -%] |
|
2 |
<body> |
|
3 |
|
|
4 |
<h1>[% HTML.escape(title) %]</h1> |
|
5 |
|
|
6 |
[% PROCESS 'liquidity_projection/_filter.html' %] |
|
7 |
|
|
8 |
[%- IF SELF.liquidity %] |
|
9 |
<hr> |
|
10 |
|
|
11 |
[% PROCESS 'liquidity_projection/_result.html' %] |
|
12 |
[% END %] |
|
13 |
|
|
14 |
</body> |
|
15 |
</html> |
Auch abrufbar als: Unified diff
Neuer Bericht »Liquiditätsvorschau«