+sub action_showdetails {
+ my ($self, %params) = @_;
+
+ my @bindata;
+ my $bins = SL::DB::Manager::Bin->get_all(with_objects => ['warehouse' ]);
+ my %bins_by_id = map { $_->id => $_ } @$bins;
+ my $inventories = SL::DB::Manager::Inventory->get_all(where => [ parts_id => $self->part->id],
+ with_objects => ['parts', 'trans_type' ], sort_by => 'bin_id ASC');
+ foreach my $bin (@{ $bins }) {
+ $bin->{qty} = 0;
+ }
+
+ foreach my $inv (@{ $inventories }) {
+ my $bin = $bins_by_id{ $inv->bin_id };
+ $bin->{qty} += $inv->qty;
+ $bin->{unit} = $inv->parts->unit;
+ }
+ my $sum = 0;
+ for my $bin (@{ $bins }) {
+ push @bindata , {
+ 'warehouse' => $bin->warehouse->description,
+ 'description' => $bin->description,
+ 'qty' => $bin->{qty},
+ 'unit' => $bin->{unit},
+ } if $bin->{qty} != 0;
+
+ $sum += $bin->{qty};
+ }
+
+ my $todate = DateTime->now_local;
+ my $fromdate = DateTime->now_local->add_duration(DateTime::Duration->new(years => -1));
+ my $average = 0;
+ foreach my $inv (@{ $inventories }) {
+ $average += abs($inv->qty) if $inv->shippingdate && $inv->trans_type->direction eq 'out' &&
+ DateTime->compare($inv->shippingdate,$fromdate) != -1 &&
+ DateTime->compare($inv->shippingdate,$todate) == -1;
+ }
+ my $openitems = SL::DB::Manager::OrderItem->get_all(where => [ parts_id => $self->part->id, 'order.closed' => 0 ],
+ with_objects => ['order'],);
+ my ($not_delivered, $ordered) = 0;
+ for my $openitem (@{ $openitems }) {
+ if($openitem -> order -> type eq 'sales_order') {
+ $not_delivered += $openitem->qty - $openitem->shipped_qty;
+ } elsif ( $openitem->order->type eq 'purchase_order' ) {
+ $ordered += $openitem->qty - $openitem->delivered_qty;
+ }
+ }
+
+ my $stock_amounts = $self->part->get_simple_stock_sql;
+
+ my $output = SL::Presenter->get->render('part/showdetails',
+ part => $self->part,
+ stock_amounts => $stock_amounts,
+ average => $average/12,
+ fromdate => $fromdate,
+ todate => $todate,
+ sum => $sum,
+ not_delivered => $not_delivered,
+ ordered => $ordered,
+ print_options => SL::Helper::PrintOptions->get_print_options(
+ form => Form->new(
+ type => 'part',
+ printers => SL::DB::Manager::Printer->get_all_sorted,
+ ),
+ options => {
+ dialog_name_prefix => 'print_options.',
+ show_headers => 1,
+ no_queue => 1,
+ no_postscript => 1,
+ no_opendocument => 1,
+ hide_language_id_print => 1,
+ no_html => 1,
+ },
+ ),
+ );
+ $self->render(\$output, { layout => 0, process => 0 });
+}
+
+sub action_print_label {
+ my ($self) = @_;
+ # TODO: implement
+ return $self->render('generic/error', { layout => 1 }, label_error => t8('Not implemented yet!'));
+}
+
+sub action_export_assembly_assortment_components {
+ my ($self) = @_;
+
+ my $bom_or_charge = $self->part->is_assembly ? 'bom' : 'charge';
+
+ my @rows = ([
+ $::locale->text('Partnumber'),
+ $::locale->text('Description'),
+ $::locale->text('Type'),
+ $::locale->text('Classification'),
+ $::locale->text('Qty'),
+ $::locale->text('Unit'),
+ $self->part->is_assembly ? $::locale->text('BOM') : $::locale->text('Charge'),
+ $::locale->text('Line Total'),
+ $::locale->text('Sellprice'),
+ $::locale->text('Lastcost'),
+ $::locale->text('Partsgroup'),
+ ]);
+
+ foreach my $item (@{ $self->part->items }) {
+ my $part = $item->part;
+
+ my @row = (
+ $part->partnumber,
+ $part->description,
+ SL::Presenter::Part::type_abbreviation($part->part_type),
+ SL::Presenter::Part::classification_abbreviation($part->classification_id),
+ $item->qty_as_number,
+ $part->unit,
+ $item->$bom_or_charge ? $::locale->text('yes') : $::locale->text('no'),
+ $::form->format_amount(\%::myconfig, $item->linetotal_sellprice, 3, 0),
+ $part->sellprice_as_number,
+ $part->lastcost_as_number,
+ $part->partsgroup ? $part->partsgroup->partsgroup : '',
+ );
+
+ push @rows, \@row;
+ }
+
+ my $csv = Text::CSV_XS->new({
+ sep_char => ';',
+ eol => "\n",
+ binary => 1,
+ });
+
+ my ($file_handle, $file_name) = File::Temp::tempfile;
+
+ binmode $file_handle, ":encoding(utf8)";
+
+ $csv->print($file_handle, $_) for @rows;
+
+ $file_handle->close;
+
+ my $type_prefix = $self->part->is_assembly ? 'assembly' : 'assortment';
+ my $part_number = $self->part->partnumber;
+ $part_number =~ s{[^[:word:]]+}{_}g;
+ my $timestamp = strftime('_%Y-%m-%d_%H-%M-%S', localtime());
+ my $attachment_name = sprintf('%s_components_%s_%s.csv', $type_prefix, $part_number, $timestamp);
+
+ $self->send_file(
+ $file_name,
+ content_type => 'text/csv',
+ name => $attachment_name,
+ );
+
+}
+