Revision 76779674
Von Tamino Steinert vor 5 Monaten hinzugefügt
SL/LiquidityProjection.pm | ||
---|---|---|
5 | 5 |
use List::MoreUtils qw(uniq); |
6 | 6 |
|
7 | 7 |
use SL::DBUtils; |
8 |
use SL::Helper::DateTime; |
|
8 | 9 |
use SL::DB::PeriodicInvoicesConfig; |
9 | 10 |
|
10 | 11 |
sub new { |
... | ... | |
109 | 110 |
|
110 | 111 |
$params{months} ||= 6; |
111 | 112 |
|
112 |
# 1. Auslesen aller erzeugten periodischen Rechnungen im |
|
113 |
# Betrachtungszeitraum |
|
114 |
my $q_min_date = $dbh->quote($self->{min_date} . '-01'); |
|
115 |
$query = <<SQL; |
|
116 |
SELECT pi.config_id, to_char(pi.period_start_date, 'YYYY-MM') AS period_start_date |
|
117 |
FROM periodic_invoices pi |
|
118 |
LEFT JOIN periodic_invoices_configs pcfg ON (pi.config_id = pcfg.id) |
|
119 |
WHERE pcfg.active |
|
120 |
AND NOT pcfg.periodicity = 'o' |
|
121 |
AND (pi.period_start_date >= to_date($q_min_date, 'YYYY-MM-DD')) |
|
122 |
SQL |
|
123 |
|
|
124 |
my %periodic_invoices; |
|
125 |
$sth = prepare_execute_query($::form, $dbh, $query); |
|
126 |
while ($ref = $sth->fetchrow_hashref) { |
|
127 |
$periodic_invoices{ $ref->{config_id} } ||= { }; |
|
128 |
$periodic_invoices{ $ref->{config_id} }->{ $ref->{period_start_date} } = 1; |
|
129 |
} |
|
130 |
$sth->finish; |
|
131 |
|
|
132 |
# 2. Auslesen aktiver Wartungsvertragskonfigurationen |
|
133 |
$query = <<SQL; |
|
134 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal, oi.recurring_billing_mode, |
|
135 |
bg.description AS buchungsgruppe, |
|
136 |
pg.partsgroup AS parts_group, |
|
137 |
CASE WHEN COALESCE(e.name, '') = '' THEN e.login ELSE e.name END AS salesman, |
|
138 |
pcfg.periodicity, pcfg.order_value_periodicity, pcfg.id AS config_id, |
|
139 |
EXTRACT(year FROM pcfg.start_date) AS start_year, EXTRACT(month FROM pcfg.start_date) AS start_month |
|
140 |
FROM orderitems oi |
|
141 |
LEFT JOIN oe ON (oi.trans_id = oe.id) |
|
142 |
LEFT JOIN periodic_invoices_configs pcfg ON (oi.trans_id = pcfg.oe_id) |
|
143 |
LEFT JOIN parts p ON (oi.parts_id = p.id) |
|
144 |
LEFT JOIN buchungsgruppen bg ON (p.buchungsgruppen_id = bg.id) |
|
145 |
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id) |
|
146 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id) |
|
147 |
WHERE pcfg.active |
|
148 |
AND (pcfg.periodicity <> 'o') |
|
149 |
AND ( (oi.recurring_billing_mode = 'always') |
|
150 |
OR ( (oi.recurring_billing_mode = 'once') |
|
151 |
AND (oi.recurring_billing_invoice_id IS NULL))) |
|
152 |
SQL |
|
153 |
|
|
154 |
# 3. Iterieren über Saldierungsintervalle, vormerken |
|
155 | 113 |
my @scentries; |
156 |
$sth = prepare_execute_query($::form, $dbh, $query); |
|
157 |
while ($ref = $sth->fetchrow_hashref) { |
|
158 |
my ($year, $month) = ($ref->{start_year}, $ref->{start_month}); |
|
159 |
my $date; |
|
160 |
|
|
161 |
while (($date = _the_date($year, $month)) le $self->{max_date}) { |
|
162 |
my $billing_len = $SL::DB::PeriodicInvoicesConfig::PERIOD_LENGTHS{ $ref->{periodicity} } || 1; |
|
163 |
|
|
164 |
if (($date ge $self->{min_date}) && (!$periodic_invoices{ $ref->{config_id} } || !$periodic_invoices{ $ref->{config_id} }->{$date})) { |
|
165 |
if ($ref->{recurring_billing_mode} eq 'once') { |
|
166 |
push @scentries, { buchungsgruppe => $ref->{buchungsgruppe}, |
|
167 |
salesman => $ref->{salesman}, |
|
168 |
linetotal => $ref->{linetotal}, |
|
169 |
date => $date, |
|
170 |
}; |
|
171 |
last; |
|
172 |
} |
|
173 |
|
|
174 |
my $order_value_periodicity = $ref->{order_value_periodicity} eq 'p' ? $ref->{periodicity} : $ref->{order_value_periodicity}; |
|
175 |
my $order_value_len = $SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIOD_LENGTHS{$order_value_periodicity} || 1; |
|
176 |
|
|
177 |
push @scentries, { buchungsgruppe => $ref->{buchungsgruppe}, |
|
178 |
salesman => $ref->{salesman}, |
|
179 |
linetotal => $ref->{linetotal} * $billing_len / $order_value_len, |
|
180 |
date => $date, |
|
181 |
parts_group => $ref->{parts_group}, |
|
182 |
}; |
|
183 |
} |
|
184 | 114 |
|
185 |
($year, $month) = _fix_date($year, $month + $billing_len); |
|
115 |
# 1. Auslesen aller erzeugten periodischen Rechnungen im Betrachtungszeitraum |
|
116 |
my $configs = SL::DB::Manager::PeriodicInvoicesConfig->get_all(query => [ active => 1 ]); |
|
117 |
foreach my $config (@{ $configs }) { |
|
118 |
my $open_orders = $config->get_open_orders_for_period( |
|
119 |
end_date => DateTime->from_ymd( |
|
120 |
$self->{max_date} . '-01' |
|
121 |
)->add(months => 1, days => -1) |
|
122 |
); |
|
123 |
foreach my $order (@$open_orders) { |
|
124 |
my $month_date = _the_date($order->reqdate->year, $order->reqdate->month); |
|
125 |
foreach my $order_item ($order->items()) { |
|
126 |
push @scentries, { |
|
127 |
buchungsgruppe => $order_item->part->buchungsgruppe->description, |
|
128 |
salesman => $order->salesman ? $order->salesman->name : $order->employee->name, |
|
129 |
linetotal => $order_item->qty * (1 - $order_item->discount) * $order_item->sellprice, |
|
130 |
date => $month_date, |
|
131 |
parts_group => $order_item->part->partsgroup, |
|
132 |
}; |
|
133 |
} |
|
186 | 134 |
} |
187 | 135 |
} |
188 |
$sth->finish; |
|
189 | 136 |
|
190 |
# 4. Auslesen offener Aufträge
|
|
137 |
# 2. Auslesen offener Aufträge
|
|
191 | 138 |
$query = <<SQL; |
192 | 139 |
SELECT (oi.qty * (1 - oi.discount) * oi.sellprice) AS linetotal, |
193 | 140 |
bg.description AS buchungsgruppe, |
... | ... | |
202 | 149 |
LEFT JOIN employee e ON (COALESCE(oe.salesman_id, oe.employee_id) = e.id) |
203 | 150 |
WHERE oe.record_type = 'sales_order' |
204 | 151 |
AND NOT COALESCE(oe.closed, FALSE) |
205 |
AND (oe.id NOT IN (SELECT oe_id FROM periodic_invoices_configs WHERE periodicity <> 'o'))
|
|
152 |
AND (oe.id NOT IN (SELECT oe_id FROM periodic_invoices_configs)) |
|
206 | 153 |
SQL |
207 | 154 |
|
208 |
# 5. Initialisierung der Datenstrukturen zum Speichern der
|
|
155 |
# 3. Initialisierung der Datenstrukturen zum Speichern der
|
|
209 | 156 |
# Ergebnisse |
210 | 157 |
my @entries = selectall_hashref_query($::form, $dbh, $query); |
211 | 158 |
my @salesmen = uniq map { $_->{salesman} } (@entries, @scentries); |
... | ... | |
232 | 179 |
}, |
233 | 180 |
}; |
234 | 181 |
|
235 |
# 6. Aufsummieren der Auftragspositionen
|
|
182 |
# 4. Aufsummieren der Auftragspositionen
|
|
236 | 183 |
foreach $ref (@entries) { |
237 | 184 |
my $date = $self->_date_for($ref); |
238 | 185 |
|
... | ... | |
243 | 190 |
$projection->{parts_group}->{ $ref->{parts_group} }->{$date} += $ref->{linetotal}; |
244 | 191 |
} |
245 | 192 |
|
246 |
# 7. Aufsummieren der Wartungsvertragspositionen
|
|
193 |
# 5. Aufsummieren der Wartungsvertragspositionen
|
|
247 | 194 |
foreach $ref (@scentries) { |
248 | 195 |
my $date = $ref->{date}; |
249 | 196 |
|
... | ... | |
346 | 293 |
$calc_params{end_date} //= $calc_params{start_date}->clone->add(years => 1); |
347 | 294 |
|
348 | 295 |
foreach my $config (@{ $configs }) { |
349 |
my @dates = $config->calculate_invoice_dates(%calc_params); |
|
350 |
next unless @dates; |
|
351 | 296 |
|
352 |
my $order = SL::DB::Order->new(id => $config->oe_id)->load(with_objects => [ qw(customer employee) ]); |
|
353 |
$order->{is_recurring} = 1; |
|
297 |
my $rec_orders = $config->get_open_orders_for_period(%calc_params); |
|
298 |
next unless scalar $rec_orders; |
|
299 |
|
|
300 |
$_->{is_recurring} = 1 for @$rec_orders; |
|
354 | 301 |
|
355 |
push @recurring_orders, $order;
|
|
302 |
push @recurring_orders, @$rec_orders;
|
|
356 | 303 |
} |
357 | 304 |
|
358 | 305 |
my @where = ( |
Auch abrufbar als: Unified diff
S:LiquidityProjection: Nutze Helferfunktion zum Berechnen von Wied. Rech.