Revision 541a31c2
Von Jan Büren vor mehr als 9 Jahren hinzugefügt
SL/Controller/DeliveryValueReport.pm | ||
---|---|---|
74 | 74 |
|
75 | 75 |
my @sortable = qw(reqdate customer vendor ordnumber partnumber description); |
76 | 76 |
|
77 |
# if csv report export no units (better calculation in
|
|
77 |
# if csv report export no units |
|
78 | 78 |
my $rp_csv_mod = ($csv_option eq 'CSV') ? 1 : ''; |
79 | 79 |
|
80 | 80 |
my %column_defs = ( |
81 |
reqdate => { sub => sub { $_[0]->reqdate_as_date || $_[0]->order->reqdate_as_date } }, |
|
82 |
description => { sub => sub { $_[0]->description }, |
|
83 |
obj_link => sub { $self->link_to($_[0]->part) } }, |
|
84 |
partnumber => { sub => sub { $_[0]->part->partnumber }, |
|
85 |
obj_link => sub { $self->link_to($_[0]->part) } }, |
|
81 |
reqdate => { sub => sub { $_[0]->reqdate_as_date || $_[0]->order->reqdate_as_date } },
|
|
82 |
description => { sub => sub { $_[0]->description },
|
|
83 |
obj_link => sub { $self->link_to($_[0]->part) } },
|
|
84 |
partnumber => { sub => sub { $_[0]->part->partnumber },
|
|
85 |
obj_link => sub { $self->link_to($_[0]->part) } },
|
|
86 | 86 |
qty => { sub => sub { $_[0]->qty_as_number . |
87 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
87 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } },
|
|
88 | 88 |
netto_qty => { sub => sub { $::form->format_amount(\%::myconfig, |
89 | 89 |
($_[0]->qty * $_[0]->sellprice * (1 - $_[0]->discount) / |
90 |
($_[0]->price_factor || 1), 2)) },}, |
|
91 |
unit => { sub => sub { $_[0]->unit },
|
|
92 |
visible => $rp_csv_mod },
|
|
90 |
($_[0]->price_factor || 1), 2)) },},
|
|
91 |
unit => { sub => sub { $_[0]->unit }, |
|
92 |
visible => $rp_csv_mod }, |
|
93 | 93 |
shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{shipped_qty}, 2) . |
94 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
95 |
netto_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_shipped_qty}, 2) },}, |
|
96 |
not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]->qty - $_[0]{shipped_qty} - $_[0]{delivered_qty} - $_[0]{do_closed_qty}, 2) . |
|
97 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
94 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
95 |
netto_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_shipped_qty}, 2) },}, |
|
96 |
not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]->qty - $_[0]{shipped_qty} |
|
97 |
- $_[0]{delivered_qty} - $_[0]{do_closed_qty}, 2) . |
|
98 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
98 | 99 |
delivered_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{delivered_qty}, 2) . |
99 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } },
|
|
100 |
netto_delivered_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_delivered_qty}, 2) },},
|
|
101 |
|
|
102 |
netto_not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig,(
|
|
103 |
($_[0]->qty - $_[0]{shipped_qty} - $_[0]{delivered_qty} - $_[0]{do_closed_qty})
|
|
104 |
* ($_[0]->sellprice * (1 - $_[0]->discount) / ($_[0]->price_factor || 1)), 2)) },},
|
|
100 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) } }, |
|
101 |
netto_delivered_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_delivered_qty}, 2) },},
|
|
102 |
netto_not_shipped_qty => { sub => sub { $::form->format_amount(\%::myconfig,(($_[0]->qty - |
|
103 |
$_[0]{shipped_qty} - $_[0]{delivered_qty} - $_[0]{do_closed_qty})
|
|
104 |
* ($_[0]->sellprice * (1 - $_[0]->discount) /
|
|
105 |
($_[0]->price_factor || 1)), 2)) },},
|
|
105 | 106 |
do_closed_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{do_closed_qty}, 2) . |
106 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) },}, |
|
107 |
|
|
108 |
netto_do_closed_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_do_closed_qty}, 2) }, |
|
109 |
visible => $mode eq 'delivery_value_report' }, |
|
110 |
ordnumber => { sub => sub { $_[0]->order->ordnumber }, |
|
111 |
obj_link => sub { $self->link_to($_[0]->order) } }, |
|
112 |
vendor => { sub => sub { $_[0]->order->vendor->name }, |
|
107 |
($rp_csv_mod ? '' : ' ' . $_[0]->unit) },}, |
|
108 |
netto_do_closed_qty => { sub => sub { $::form->format_amount(\%::myconfig, $_[0]{netto_do_closed_qty}, 2) },}, |
|
109 |
ordnumber => { sub => sub { $_[0]->order->ordnumber }, |
|
110 |
obj_link => sub { $self->link_to($_[0]->order) } }, |
|
111 |
vendor => { sub => sub { $_[0]->order->vendor->name }, |
|
113 | 112 |
visible => $vc eq 'vendor', |
114 |
obj_link => sub { $self->link_to($_[0]->order->vendor) } },
|
|
115 |
customer => { sub => sub { $_[0]->order->customer->name },
|
|
113 |
obj_link => sub { $self->link_to($_[0]->order->vendor) } }, |
|
114 |
customer => { sub => sub { $_[0]->order->customer->name }, |
|
116 | 115 |
visible => $vc eq 'customer', |
117 |
obj_link => sub { $self->link_to($_[0]->order->customer) } },
|
|
116 |
obj_link => sub { $self->link_to($_[0]->order->customer) } }, |
|
118 | 117 |
); |
119 | 118 |
|
120 | 119 |
$column_defs{$_}->{text} = $sort_columns{$_} for keys %column_defs; |
... | ... | |
123 | 122 |
std_column_visibility => 1, |
124 | 123 |
controller_class => 'DeliveryValueReport', |
125 | 124 |
output_format => 'HTML', |
126 |
top_info_text => ($vc eq 'customer') ? (($mode eq 'delivery_plan') ? $::locale->text('Delivery Plan for currently outstanding sales orders') : |
|
127 |
$::locale->text('Delivery Value Report for currently open sales orders')) : |
|
128 |
($mode eq 'delivery_value_report') ? $::locale->text('Delivery Value Report for currently outstanding purchase orders') : |
|
129 |
$::locale->text('Delivery Plan for currently outstanding purchase orders'), |
|
130 |
title => ($mode eq 'delivery_plan') ? $::locale->text('Delivery Plan') : $::locale->text('Delivery Value Report'), |
|
125 |
top_info_text => ($vc eq 'customer') ? t8('Delivery Value Report for currently open sales orders') : |
|
126 |
t8('Delivery Value Report for currently outstanding purchase orders'), |
|
127 |
title => $::locale->text('Delivery Value Report'), |
|
131 | 128 |
allow_pdf_export => 1, |
132 | 129 |
allow_csv_export => 1, |
133 | 130 |
); |
... | ... | |
154 | 151 |
sub make_filter_summary { |
155 | 152 |
my ($self) = @_; |
156 | 153 |
my $vc = $self->vc; |
157 |
my $mode = 'delivery_value_report'; |
|
158 | 154 |
my ($business, $employee); |
159 | 155 |
|
160 | 156 |
my $filter = $::form->{filter} || {}; |
... | ... | |
179 | 175 |
[ $employee, $::locale->text('Employee') ], |
180 | 176 |
); |
181 | 177 |
|
178 |
# flags for with_object 'part' |
|
182 | 179 |
my %flags = ( |
183 | 180 |
part => $::locale->text('Parts'), |
184 | 181 |
service => $::locale->text('Services'), |
... | ... | |
203 | 200 |
sub init_models { |
204 | 201 |
my ($self) = @_; |
205 | 202 |
my $vc = $self->vc; |
206 |
$main::lxdebug->message(0, 'vc hier:' . $vc); |
|
207 | 203 |
SL::Controller::Helper::GetModels->new( |
208 | 204 |
controller => $self, |
209 | 205 |
model => 'OrderItem', |
... | ... | |
214 | 210 |
}, |
215 | 211 |
%sort_columns, |
216 | 212 |
}, |
217 |
# show only open orders |
|
218 |
query => [ 'order.closed' => '0', "order.${vc}_id" => { gt => 0 } ], |
|
219 |
with_objects => [ 'order', "order.$vc" ], |
|
213 |
# show only open (sales|purchase) orders |
|
214 |
query => [ 'order.closed' => '0', "order.${vc}_id" => { gt => 0 }, |
|
215 |
'order.quotation' => 0 ], |
|
216 |
with_objects => [ 'order', "order.$vc", 'part' ], |
|
220 | 217 |
additional_url_params => { vc => $vc}, |
221 |
);
|
|
218 |
) |
|
222 | 219 |
} |
223 | 220 |
|
224 | 221 |
sub init_vc { |
225 |
return $::form->{vc} if ($::form->{vc} eq 'customer' || $::form->{vc} eq 'vendor') || croak "self (DeliveryPlan) has no vc defined";
|
|
222 |
return $::form->{vc} if ($::form->{vc} eq 'customer' || $::form->{vc} eq 'vendor') || croak "self (DeliveryValueReport) has no vc defined";
|
|
226 | 223 |
} |
227 | 224 |
sub init_all_employees { |
228 | 225 |
return SL::DB::Manager::Employee->get_all_sorted; |
... | ... | |
259 | 256 |
sub calc_qtys_price { |
260 | 257 |
my ($self, $orderitems) = @_; |
261 | 258 |
# using $orderitem->shipped_qty 40 times is far too slow. need to do it manually |
262 |
# |
|
259 |
# also for calc net values
|
|
263 | 260 |
|
264 | 261 |
return unless scalar @$orderitems; |
265 | 262 |
|
266 | 263 |
my %orderitems_by_id = map { $_->id => $_ } @$orderitems; |
267 | 264 |
|
268 | 265 |
my $query = <<SQL; |
269 |
SELECT oi.id, doi.qty, doi.qty, doi.unit, doe.delivered, doe.closed, -- dois.qty as qty_stocked,
|
|
266 |
SELECT oi.id, doi.qty, doi.unit, doe.delivered, doe.closed,
|
|
270 | 267 |
oi.sellprice, oi.discount, oi.price_factor |
271 | 268 |
FROM record_links rl |
272 | 269 |
INNER JOIN delivery_order_items doi ON (doi.id = rl.to_id) |
273 | 270 |
INNER JOIN orderitems oi ON (oi.id = rl.from_id) |
274 | 271 |
INNER JOIN delivery_orders doe ON (doe.id = doi.delivery_order_id) |
275 |
--INNER JOIN delivery_order_items_stock dois ON (doi.id = dois.delivery_order_item_id) |
|
276 | 272 |
WHERE rl.from_table = 'orderitems' |
277 | 273 |
AND rl.to_table = 'delivery_order_items' |
278 | 274 |
AND oi.id IN (@{[ join ', ', ("?")x @$orderitems ]}) |
... | ... | |
285 | 281 |
$item->{shipped_qty} ||= 0; |
286 | 282 |
$item->{delivered_qty} ||= 0; |
287 | 283 |
$item->{do_closed_qty} ||= 0; |
288 |
$item->{shipped_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} unless ($row->{delivered} || $row->{closed}); |
|
289 |
$item->{delivered_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{delivered} && !$row->{closed}); |
|
290 |
$item->{do_closed_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{closed}); |
|
291 |
#$item->{do_closed_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty_stocked} if ($row->{closed}); |
|
284 |
$item->{shipped_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} unless ($row->{delivered} || $row->{closed}); |
|
285 |
$item->{delivered_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{delivered} && !$row->{closed}); |
|
286 |
$item->{do_closed_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if ($row->{closed}); |
|
292 | 287 |
$item->{not_shipped_qty} += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} unless ($row->{delivered}); |
293 |
# my $price_factor = $self->price_factor || 1; |
|
294 |
#$self->_delivered_qty; |
|
295 |
#$item->{netto_qty} += $row->{qty} * $row->{sellprice} * (1 - $row->{discount} ) / ($row->{price_factor} || 1); |
|
296 |
# no sum |
|
297 |
$item->{netto_shipped_qty} = $item->{shipped_qty} * $row->{sellprice} * (1 - $row->{discount} ) / ($row->{price_factor} || 1); |
|
298 |
# $item->{netto_not_shipped_qty} += $item->{shipped_qty} * $row->{sellprice} * (1 - $row->{discount} ) / ($row->{price_factor} || 1); |
|
299 |
$item->{netto_delivered_qty} = $item->{delivered_qty} * $row->{sellprice} * (1 - $row->{discount} ) / ($row->{price_factor} || 1); |
|
300 |
$item->{netto_do_closed_qty} = $item->{do_closed_qty} * $row->{sellprice} * (1 - $row->{discount} ) / ($row->{price_factor} || 1); |
|
288 |
|
|
289 |
my $price_factor = $row->{price_factor} || 1; |
|
290 |
$item->{netto_shipped_qty} = $item->{shipped_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; |
|
291 |
$item->{netto_delivered_qty} = $item->{delivered_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; |
|
292 |
$item->{netto_do_closed_qty} = $item->{do_closed_qty} * $row->{sellprice} * (1 - $row->{discount} ) / $price_factor; |
|
301 | 293 |
|
302 | 294 |
} |
303 | 295 |
} |
... | ... | |
342 | 334 |
other metadata for the position has been altered. This is due to the fact that a hidden converted_from_previous_document is |
343 | 335 |
used in the position. |
344 | 336 |
|
345 |
from_table | id | to_table | id |
|
346 |
orderitems | 7 | delivery_order_items | 11 |
|
337 |
The main intelligence is this query (qty_stocked as comments): |
|
338 |
|
|
339 |
SELECT oi.id,and more metadata , -- dois.qty as qty_stocked, |
|
340 |
FROM record_links rl |
|
341 |
INNER JOIN delivery_order_items doi ON (doi.id = rl.to_id) |
|
342 |
INNER JOIN orderitems oi ON (oi.id = rl.from_id) |
|
343 |
INNER JOIN delivery_orders doe ON (doe.id = doi.delivery_order_id) |
|
344 |
--INNER JOIN delivery_order_items_stock dois ON (doi.id = dois.delivery_order_item_id) |
|
345 |
WHERE rl.from_table = 'orderitems' |
|
346 |
AND rl.to_table = 'delivery_order_items' |
|
347 |
|
|
348 |
Get all entries which were converted from orderitems to delivery_order_items (WHERE). |
|
349 |
The persistent id are in rl, therefore we can fetch orderitems and delivery_order_items. |
|
350 |
The join on delivery_orders (doe) is only needed for the current state of the delivery order (closed, delivered). |
|
347 | 351 |
|
348 | 352 |
=head1 FUNCTIONS |
349 | 353 |
|
350 | 354 |
=over 2 |
351 | 355 |
|
352 |
=item C<action_list_sales_delivery_orders> |
|
356 |
=item C<action_list> |
|
357 |
|
|
358 |
=item C<prepare_report> |
|
359 |
|
|
360 |
=item C<make_filter_summary> |
|
361 |
|
|
362 |
=item C<calc_qtys_price> |
|
363 |
|
|
364 |
=item C<link_to> |
|
365 |
|
|
366 |
=item C<init_models> |
|
367 |
|
|
368 |
=item C<init_vc> |
|
369 |
|
|
370 |
=item C<init_all_employees> |
|
371 |
|
|
372 |
=item C<init_all_businesses> |
|
373 |
|
|
374 |
=back |
|
375 |
|
|
376 |
=head1 TODOS |
|
377 |
|
|
378 |
Currently no foreign currencies and OrderItems with taxincluded are calculated / supported. The report can be easily extended |
|
379 |
for the real stocked qty. The report is really easy to implement and customise if your model is focussed straight. |
|
380 |
For long term maintaineance it would be wise to add more testcases for the conversion from orders to delivery_orders. |
|
381 |
Right now record_links are tested only from document to document and the convert_invoice method (via task server) has a |
|
382 |
test case with record_links items included. Furhtermore I personally dislike the calcs in the %columns_def, but for a quick report |
|
383 |
this is ok, though if we redesign this further, the taxincluded / currency cases should be implemented as well. |
|
384 |
|
|
385 |
|
|
386 |
=head1 AUTHOR |
|
387 |
|
|
388 |
Jan Büren E<lt>jan@kivitendo-premium.deE<gt> (based on DeliveryPlan.pm by Sven) |
|
353 | 389 |
|
354 |
L |
|
390 |
=cut |
Auch abrufbar als: Unified diff
Changelog, Kosmetik und Warenfilter für Lieferwertbericht
Doku und changelog ergänzt. Sinnvoller formatiert und model
um part erweitert, damit der Filter (Erzeugnis, Dienstleistung und
Ware) wie beim Lieferplan funktioniert.