Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 2ea1a379

Von Moritz Bunkus vor mehr als 10 Jahren hinzugefügt

  • ID 2ea1a379cc2e8992077a8a6f6e413952d1e32bfd
  • Vorgänger 41adf433
  • Nachfolger 699e686c

Neuer Bericht »Liquiditätsvorschau«

Unterschiede anzeigen:

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&auml;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&auml;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&auml;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