Revision eb1b0cbc
Von Tamino Steinert vor mehr als 1 Jahr hinzugefügt
SL/Controller/Part.pm | ||
---|---|---|
24 | 24 |
use SL::DB::PriceRuleItem; |
25 | 25 |
use SL::DB::Shop; |
26 | 26 |
use SL::Helper::Flash; |
27 |
use SL::Helper::PrintOptions; |
|
27 | 28 |
use SL::JSON; |
28 | 29 |
use SL::Locale::String qw(t8); |
29 | 30 |
use SL::MoreCommon qw(save_form); |
... | ... | |
739 | 740 |
} |
740 | 741 |
} |
741 | 742 |
|
743 |
sub action_showdetails { |
|
744 |
my ($self, %params) = @_; |
|
745 |
|
|
746 |
eval { |
|
747 |
my @bindata; |
|
748 |
my $bins = SL::DB::Manager::Bin->get_all(with_objects => ['warehouse' ]); |
|
749 |
my %bins_by_id = map { $_->id => $_ } @$bins; |
|
750 |
my $inventories = SL::DB::Manager::Inventory->get_all(where => [ parts_id => $self->part->id], |
|
751 |
with_objects => ['parts', 'trans_type' ], sort_by => 'bin_id ASC'); |
|
752 |
foreach my $bin (@{ $bins }) { |
|
753 |
$bin->{qty} = 0; |
|
754 |
} |
|
755 |
|
|
756 |
foreach my $inv (@{ $inventories }) { |
|
757 |
my $bin = $bins_by_id{ $inv->bin_id }; |
|
758 |
$bin->{qty} += $inv->qty; |
|
759 |
$bin->{unit} = $inv->parts->unit; |
|
760 |
$bin->{reserved} = defined $inv->reserve_for_id ? 1 : 0; |
|
761 |
} |
|
762 |
my $sum = 0; |
|
763 |
my $reserve_sum = 0; |
|
764 |
for my $bin (@{ $bins }) { |
|
765 |
push @bindata , { |
|
766 |
'warehouse' => $bin->warehouse->forreserve ? $bin->warehouse->description.' (R)' : $bin->warehouse->description, |
|
767 |
'description' => $bin->description, |
|
768 |
'qty' => $bin->{qty}, |
|
769 |
'unit' => $bin->{unit}, |
|
770 |
} if $bin->{qty} != 0; |
|
771 |
|
|
772 |
$sum += $bin->{qty}; |
|
773 |
if($bin->warehouse->forreserve || defined $bin->warehouse->{reserve_for_id}){ |
|
774 |
$reserve_sum += $bin->{qty}; |
|
775 |
} |
|
776 |
} |
|
777 |
# Einfacher ? $sum = $self->part->onhand |
|
778 |
my $todate = DateTime->now_local; |
|
779 |
my $fromdate = DateTime->now_local->add_duration(DateTime::Duration->new(years => -1)); |
|
780 |
my $average = 0; |
|
781 |
foreach my $inv (@{ $inventories }) { |
|
782 |
$average += abs($inv->qty) if $inv->shippingdate && $inv->trans_type->direction eq 'out' && |
|
783 |
DateTime->compare($inv->shippingdate,$fromdate) != -1 && |
|
784 |
DateTime->compare($inv->shippingdate,$todate) == -1; |
|
785 |
} |
|
786 |
my $openitems = SL::DB::Manager::OrderItem->get_all(where => [ parts_id => $self->part->id, 'order.closed' => 0 ], |
|
787 |
with_objects => ['order'],); |
|
788 |
my ($not_delivered, $ordered) = 0; |
|
789 |
for my $openitem (@{ $openitems }) { |
|
790 |
if($openitem -> order -> type eq 'sales_order') { |
|
791 |
$not_delivered += $openitem->qty - $openitem->shipped_qty; |
|
792 |
} elsif ( $openitem->order->type eq 'purchase_order' ) { |
|
793 |
$ordered += $openitem->qty - $openitem->delivered_qty; |
|
794 |
} |
|
795 |
} |
|
796 |
my $print_form = Form->new(''); |
|
797 |
my $part = $self->part; |
|
798 |
|
|
799 |
my $stock_amounts = $self->part->get_simple_stock_sql; |
|
800 |
$print_form->{type} = 'part'; |
|
801 |
$print_form->{printers} = SL::DB::Manager::Printer->get_all_sorted; |
|
802 |
my $output = SL::Presenter->get->render('part/showdetails', |
|
803 |
part => $self->part, |
|
804 |
BINS => \@bindata, |
|
805 |
stock_amounts => $stock_amounts, |
|
806 |
average => $average/12, |
|
807 |
fromdate => $fromdate, |
|
808 |
todate => $todate, |
|
809 |
sum => $sum, |
|
810 |
reserve_sum => $reserve_sum, |
|
811 |
not_delivered => $not_delivered, |
|
812 |
ordered => $ordered, |
|
813 |
type_beleg => $::form->{type}, |
|
814 |
type_id => $::form->{type_id}, |
|
815 |
maker_id => $::form->{maker_id}, |
|
816 |
drawing => $::form->{drawing}, |
|
817 |
print_options => SL::Helper::PrintOptions->get_print_options( |
|
818 |
form => $print_form, |
|
819 |
options => {dialog_name_prefix => 'print_options.', |
|
820 |
show_headers => 1, |
|
821 |
no_queue => 1, |
|
822 |
no_postscript => 1, |
|
823 |
no_opendocument => 1, |
|
824 |
hide_language_id_print => 1, |
|
825 |
no_html => 1}, |
|
826 |
), |
|
827 |
); |
|
828 |
$self->render(\$output, { layout => 0, process => 0 }); |
|
829 |
1; |
|
830 |
} or do { |
|
831 |
}; |
|
832 |
} |
|
833 |
|
|
834 |
sub action_print_label { |
|
835 |
my ($self) = @_; |
|
836 |
# TODO: implement |
|
837 |
return $self->render('generic/error', { layout => 1 }, label_error => t8('Not implemented yet!')); |
|
838 |
} |
|
839 |
|
|
742 | 840 |
sub action_export_assembly_assortment_components { |
743 | 841 |
my ($self) = @_; |
744 | 842 |
|
js/kivi.Part.js | ||
---|---|---|
22 | 22 |
$('#ic').submit(); |
23 | 23 |
}; |
24 | 24 |
|
25 |
ns.print_from_showdetail = function(part_id) { |
|
26 |
var data = $('#print_options_form').serializeArray(); |
|
27 |
data.push({ name: 'action', value: 'Part/print_label' }); |
|
28 |
data.push({ name: 'part.id', value: part_id }); |
|
29 |
$.download("controller.pl", data); |
|
30 |
}; |
|
31 |
|
|
25 | 32 |
ns.delete = function() { |
26 | 33 |
var data = $('#ic').serializeArray(); |
27 | 34 |
data.push({ name: 'action', value: 'Part/delete' }); |
templates/webpages/part/showdetails.html | ||
---|---|---|
1 |
[%- USE LxERP -%][% USE L %][% USE HTML %][%- USE JavaScript -%][% USE T8 %][%- USE Dumper %] |
|
2 |
|
|
3 |
<div style="padding-bottom: 15px"> |
|
4 |
<table style="width: 100%" border="0px" ><tbody> |
|
5 |
<tr> |
|
6 |
<td><b>[% LxERP.t8('Description') %]</b></td><td colspan="3">[% part.description %]</td> |
|
7 |
</tr> |
|
8 |
<tr> |
|
9 |
<td style="background:wheat;"><b>[% LxERP.t8('Internal Notes') %]</b></td><td colspan="3" style="background:wheat;">[% part.intnotes %]</td> |
|
10 |
</tr> |
|
11 |
<tr> |
|
12 |
<td><b>[% LxERP.t8('Default Warehouse') %]</b></td><td>[% part.warehouse.description %]</td> |
|
13 |
<td><b>[% LxERP.t8('Default Bin') %]</b></td><td>[% part.bin.description %]</td> |
|
14 |
</tr> |
|
15 |
<tr> |
|
16 |
<td><b>[% LxERP.t8('ROP') %]</b></td><td>[% part.rop_as_number %]</td> |
|
17 |
</tr> |
|
18 |
<tr> |
|
19 |
[%- IF stock_amounts.size %] |
|
20 |
<td colspan="4"><table style="width: 100%"> |
|
21 |
<tr class='listheading'> |
|
22 |
<th class="listheading">[% 'Warehouse' | $T8 %]</th> |
|
23 |
<th class="listheading">[% 'Bin' | $T8 %]</th> |
|
24 |
<th class="listheading">[% 'Chargenumber' | $T8 %]</th> |
|
25 |
<th class="listheading">[% 'Qty' | $T8 %]</th> |
|
26 |
<th class="listheading">[% 'Unit' | $T8 %]</th> |
|
27 |
</tr> |
|
28 |
[% FOREACH stock = stock_amounts %] |
|
29 |
<tr class='listrow'> |
|
30 |
<td >[% HTML.escape(stock.warehouse_description) %]</td> |
|
31 |
<td >[% IF stock.order_link %]<a target="_blank" href="[% stock.order_link %]">[% END %] |
|
32 |
[% HTML.escape(stock.bin_description) %] |
|
33 |
[% IF stock.order_link %]</a>[% END %] |
|
34 |
</td> |
|
35 |
<td >[% HTML.escape(stock.chargenumber) %]</td> |
|
36 |
<td class='numeric'>[% LxERP.format_amount(stock.qty, dec) %]</td> |
|
37 |
<td >[% HTML.escape(stock.unit) %]</td> |
|
38 |
</tr> |
|
39 |
[% IF stock.wh_lead != stock.warehouse_description %] |
|
40 |
<tr class='listheading'> |
|
41 |
<th class="listheading" >[% HTML.escape(stock.warehouse_description) %]</th> |
|
42 |
<td></td> |
|
43 |
<td></td> |
|
44 |
<td class='numeric bold'>[% LxERP.format_amount(stock.wh_run_qty, dec) %]</td> |
|
45 |
<td></td> |
|
46 |
</tr> |
|
47 |
[% END %] |
|
48 |
[% IF loop.last %] |
|
49 |
<tr class='listheading'> |
|
50 |
<th class="listheading">[% 'Total' | $T8 %]</th> |
|
51 |
<td></td> |
|
52 |
<td></td> |
|
53 |
<td class='numeric bold'>[% LxERP.format_amount(stock.run_qty, dec) %]</td> |
|
54 |
<td></td> |
|
55 |
</tr> |
|
56 |
[% END %] |
|
57 |
[% END %] |
|
58 |
[% ELSE %] |
|
59 |
<td> |
|
60 |
<p>[% 'No transactions yet.' | $T8 %]</p> |
|
61 |
[% END %] |
|
62 |
</td> |
|
63 |
</tr> |
|
64 |
<tr> |
|
65 |
<td><b>[% LxERP.t8('Sum Amount') %]</b></td><td>[% LxERP.format_amount(sum, 2) %] [% part.unit %]</td> |
|
66 |
<td rowspan="5"> |
|
67 |
[% file = part.default_partimage %] |
|
68 |
[%- IF file && INSTANCE_CONF.get_parts_show_image %] |
|
69 |
<img src="controller.pl?action=File/download&id=[% file.id %][%- IF file.version %]&version=[%- file.version %][%- END %]" alt="[% file.title %]" style="[% INSTANCE_CONF.get_parts_image_css %]"> |
|
70 |
[% END %] |
|
71 |
</td> |
|
72 |
<td rowspan="5"> |
|
73 |
[%- FOREACH file = part.get_files %] |
|
74 |
<a href="controller.pl?action=File/download&id=[% file.id %][%- IF file.version %]&version=[%- file.version %][%- END %]"> |
|
75 |
<span id="[% "filename_" _ file.id %][%- IF file.version %]_[% file.version %][%- END %]">[% file.file_name %]</span></a><br><br> |
|
76 |
[%- END %] |
|
77 |
</td> |
|
78 |
</tr> |
|
79 |
<tr> |
|
80 |
<td><b>[% LxERP.t8('Not delivered amount') %]</b></td><td colspan="3">[% LxERP.format_amount(not_delivered, 2) %] [% part.unit %]</td></tr> |
|
81 |
</tr> |
|
82 |
<tr> |
|
83 |
<td><b>[% LxERP.t8('Ordered, but not delivered (purchase)') %]</b></td><td colspan="3">[% LxERP.format_amount(ordered, 2) %] [% part.unit %]</td></tr> |
|
84 |
</tr> |
|
85 |
<tr> |
|
86 |
<td><b>[% LxERP.t8('Reserved amount') %]</b></td><td colspan="3">[% LxERP.format_amount(part.stockqty - part.onhandqty, 2) %] [% part.unit %]</td></tr> |
|
87 |
</tr> |
|
88 |
<tr> |
|
89 |
<td><b>[% LxERP.t8('Available amount') %]</b></td><td colspan="3">[% LxERP.format_amount(part.onhandqty, 2) %] [% part.unit %]</td></tr> |
|
90 |
</tr> |
|
91 |
<tr> |
|
92 |
<td><b>[% LxERP.t8('Consume average') %]</b></td><td colspan="3">[% LxERP.format_amount(average, 2) %] [% part.unit %] [% LxERP.t8('per month') %]</td></tr> |
|
93 |
<tr><td colspan="4" nowrap>([% LxERP.t8('in the time between') %] [% fromdate.to_kivitendo %] - [% todate.to_kivitendo %])</td> |
|
94 |
</tr> |
|
95 |
<tr> |
|
96 |
<td>[%- L.button_tag("return \$('#detail_menu').dialog('close');", LxERP.t8('Close Details'), class => "submit") %]</td> |
|
97 |
</tr> |
|
98 |
</tbody></table> |
|
99 |
</div> |
|
100 |
<div id="print_options" > |
|
101 |
<form id="print_options_form"> |
|
102 |
[% print_options %] |
|
103 |
<br> |
|
104 |
[% L.button_tag('kivi.Part.print_from_showdetail(' _ part.id _ ')', LxERP.t8('Print')) %] |
|
105 |
</form> |
|
106 |
</div> |
|
107 |
|
Auch abrufbar als: Unified diff
Part: Detailansicht als Popup hinzugefügt