40 |
40 |
# Monat ihre Saldierungsperiode haben, außer Wartungsverträgen, die
|
41 |
41 |
# für den jeweiligen Monat bereits abgerechnet wurden.
|
42 |
42 |
#
|
43 |
|
# Diese Werte sollen zusätzlich optional nach Verkäufer(in) und nach
|
44 |
|
# Buchungsgruppe aufgeschlüsselt werden.
|
|
43 |
# Diese Werte sollen zusätzlich optional nach Verkäufer(in),
|
|
44 |
# Buchungsgruppe und Warengruppe aufgeschlüsselt werden.
|
45 |
45 |
#
|
46 |
46 |
# Diese Lösung geht deshalb immer über die Positionen der Belege
|
47 |
|
# (wegen der Buchungsgruppe) und berechnet die Summen daraus manuell.
|
|
47 |
# (wegen der Buchungsgruppen & Warengruppen) und berechnet die Summen
|
|
48 |
# daraus manuell.
|
48 |
49 |
#
|
49 |
50 |
# Alle Aufträge, deren Lieferdatum leer ist, oder deren Lieferdatum
|
50 |
51 |
# vor dem aktuellen Monat liegt, werden in einer Kategorie 'alt'
|
... | ... | |
70 |
71 |
# Monat vorgemerkt.
|
71 |
72 |
#
|
72 |
73 |
# 4. Es werden für alle offenen Kundenaufträge die Positionen
|
73 |
|
# ausgelesen und mit Verkäufer(in), Buchungsgruppe verknüpft. Aus
|
74 |
|
# Menge, Einzelpreis und Zeilenrabatt wird die Zeilensumme berechnet.
|
|
74 |
# ausgelesen und mit Verkäufer(in), Buchungsgruppe, Warengruppe
|
|
75 |
# verknüpft. Aus Menge, Einzelpreis und Zeilenrabatt wird die
|
|
76 |
# Zeilensumme berechnet.
|
75 |
77 |
#
|
76 |
78 |
# 5. Mit den Informationen aus 3. und 4. werden Datenstrukturen
|
77 |
79 |
# initialisiert, die für die Gesamtsummen, für alle Verkäufer(innen),
|
78 |
|
# für alle Buchungsgruppen, für alle Monate Werte enthalten.
|
|
80 |
# für alle Buchungsgruppen, für alle Warengruppen, für alle Monate
|
|
81 |
# Werte enthalten.
|
79 |
82 |
#
|
80 |
83 |
# 6. Es wird über alle Einträge aus 4. iteriert. Die Zeilensummen
|
81 |
84 |
# werden in den entsprechenden Datenstrukturen aus 5. addiert.
|
... | ... | |
94 |
97 |
# den Aufträgen nie vorgekommen ist (sprich Rechnung enthält
|
95 |
98 |
# Positionen, die im Auftrag nicht enthalten sind, und die komplett
|
96 |
99 |
# andere Buchungsgruppen verwenden), so wird schlicht die allererste
|
97 |
|
# in 4. gefundene Buchungsgruppe damit belastet.
|
|
100 |
# in 4. gefundene Buchungsgruppe damit belastet. Analog passiert dies
|
|
101 |
# auch für Warengruppen.
|
98 |
102 |
|
99 |
103 |
sub create {
|
100 |
104 |
my ($self) = @_;
|
... | ... | |
129 |
133 |
$query = <<SQL;
|
130 |
134 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal,
|
131 |
135 |
bg.description AS buchungsgruppe,
|
|
136 |
pg.partsgroup AS parts_group,
|
132 |
137 |
CASE WHEN COALESCE(e.name, '') = '' THEN e.login ELSE e.name END AS salesman,
|
133 |
138 |
pcfg.periodicity, pcfg.order_value_periodicity, pcfg.id AS config_id,
|
134 |
139 |
EXTRACT(year FROM pcfg.start_date) AS start_year, EXTRACT(month FROM pcfg.start_date) AS start_month
|
... | ... | |
137 |
142 |
LEFT JOIN periodic_invoices_configs pcfg ON (oi.trans_id = pcfg.oe_id)
|
138 |
143 |
LEFT JOIN parts p ON (oi.parts_id = p.id)
|
139 |
144 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id)
|
|
145 |
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
|
140 |
146 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id)
|
141 |
147 |
WHERE pcfg.active
|
142 |
148 |
AND NOT pcfg.periodicity = 'o'
|
... | ... | |
172 |
178 |
$query = <<SQL;
|
173 |
179 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal,
|
174 |
180 |
bg.description AS buchungsgruppe,
|
|
181 |
pg.partsgroup AS parts_group,
|
175 |
182 |
CASE WHEN COALESCE(e.name, '') = '' THEN e.login ELSE e.name END AS salesman,
|
176 |
183 |
oe.ordnumber, EXTRACT(month FROM oe.reqdate) AS month, EXTRACT(year FROM oe.reqdate) AS year
|
177 |
184 |
FROM orderitems oi
|
178 |
185 |
LEFT JOIN oe ON (oi.trans_id = oe.id)
|
179 |
186 |
LEFT JOIN parts p ON (oi.parts_id = p.id)
|
180 |
187 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id)
|
|
188 |
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
|
181 |
189 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id)
|
182 |
190 |
WHERE (oe.customer_id IS NOT NULL)
|
183 |
191 |
AND NOT COALESCE(oe.quotation, FALSE)
|
... | ... | |
190 |
198 |
my @entries = selectall_hashref_query($::form, $dbh, $query);
|
191 |
199 |
my @salesmen = uniq map { $_->{salesman} } (@entries, @scentries);
|
192 |
200 |
my @buchungsgruppen = uniq map { $_->{buchungsgruppe} } (@entries, @scentries);
|
|
201 |
my @parts_groups = uniq map { $_->{parts_group} } (@entries, @scentries);
|
193 |
202 |
my @now = localtime;
|
194 |
203 |
my @dates = map { $self->_date_for($now[5] + 1900, $now[4] + $_) } (0..$self->{params}->{months} + 1);
|
195 |
204 |
my %dates_by_ordnumber = map { $_->{ordnumber} => $self->_date_for($_) } @entries;
|
... | ... | |
202 |
211 |
support => { map { $_ => 0 } @dates },
|
203 |
212 |
salesman => { map { $_ => { map { $_ => 0 } @dates } } @salesmen },
|
204 |
213 |
buchungsgruppe => { map { $_ => { map { $_ => 0 } @dates } } @buchungsgruppen },
|
|
214 |
parts_group => { map { $_ => { map { $_ => 0 } @dates } } @parts_groups },
|
205 |
215 |
sorted => { month => [ sort { ($date_sorter{$a} || $a) cmp ($date_sorter{$b} || $b) } @dates ],
|
206 |
216 |
salesman => [ sort { $a cmp $b } @salesmen ],
|
207 |
217 |
buchungsgruppe => [ sort { $a cmp $b } @buchungsgruppen ],
|
|
218 |
parts_group => [ sort { $a cmp $b } @parts_groups ],
|
208 |
219 |
type => [ qw(order partial support) ],
|
209 |
220 |
},
|
210 |
221 |
};
|
... | ... | |
217 |
228 |
$projection->{order}->{$date} += $ref->{linetotal};
|
218 |
229 |
$projection->{salesman}->{ $ref->{salesman} }->{$date} += $ref->{linetotal};
|
219 |
230 |
$projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} }->{$date} += $ref->{linetotal};
|
|
231 |
$projection->{parts_group}->{ $ref->{parts_group} }->{$date} += $ref->{linetotal};
|
220 |
232 |
}
|
221 |
233 |
|
222 |
234 |
# 7. Aufsummieren der Wartungsvertragspositionen
|
... | ... | |
227 |
239 |
$projection->{support}->{$date} += $ref->{linetotal};
|
228 |
240 |
$projection->{salesman}->{ $ref->{salesman} }->{$date} += $ref->{linetotal};
|
229 |
241 |
$projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} }->{$date} += $ref->{linetotal};
|
|
242 |
$projection->{parts_group}->{ $ref->{parts_group} }->{$date} += $ref->{linetotal};
|
230 |
243 |
}
|
231 |
244 |
|
232 |
245 |
if (%dates_by_ordnumber) {
|
... | ... | |
235 |
248 |
$query = <<SQL;
|
236 |
249 |
SELECT (i.qty * (1 - i.discount) * i.sellprice) AS linetotal,
|
237 |
250 |
bg.description AS buchungsgruppe,
|
|
251 |
pg.partsgroup AS parts_group,
|
238 |
252 |
ar.ordnumber
|
239 |
253 |
FROM invoice i
|
240 |
254 |
LEFT JOIN ar ON (i.trans_id = ar.id)
|
241 |
255 |
LEFT JOIN parts p ON (i.parts_id = p.id)
|
242 |
256 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id)
|
|
257 |
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
|
243 |
258 |
WHERE (ar.ordnumber IN ($ordnumbers))
|
244 |
259 |
SQL
|
245 |
260 |
|
... | ... | |
250 |
265 |
my $date = $dates_by_ordnumber{ $ref->{ordnumber} } || die;
|
251 |
266 |
my $salesman = $salesman_by_ordnumber{ $ref->{ordnumber} } || die;
|
252 |
267 |
my $buchungsgruppe = $projection->{buchungsgruppe}->{ $ref->{buchungsgruppe} } ? $ref->{buchungsgruppe} : $buchungsgruppen[0];
|
|
268 |
my $parts_group = $projection->{parts_group}->{ $ref->{parts_group} } ? $ref->{parts_group} : $parts_groups[0];
|
253 |
269 |
|
254 |
270 |
$projection->{partial}->{$date} -= $ref->{linetotal};
|
255 |
271 |
$projection->{total}->{$date} -= $ref->{linetotal};
|
256 |
272 |
$projection->{salesman}->{$salesman}->{$date} -= $ref->{linetotal};
|
257 |
273 |
$projection->{buchungsgruppe}->{$buchungsgruppe}->{$date} -= $ref->{linetotal};
|
|
274 |
$projection->{parts_group}->{$parts_group}->{$date} -= $ref->{linetotal};
|
258 |
275 |
}
|
259 |
276 |
}
|
260 |
277 |
|
Liquiditätsübersicht: aufschlüsseln nach Warengruppen