+sub _calculate_invoice {
+ my ($self, $data, %params) = @_;
+
+ return unless $data->{invoice};
+}
+
+sub _calculate_assembly_item {
+ my ($self, $data, $part, $total_qty, $base_factor) = @_;
+
+ return 0 unless $::eur && $data->{is_invoice};
+ return _calculate_part_service_item($self, $data, $part, $total_qty) unless $part->is_assembly;
+
+ my $allocated = 0;
+ foreach my $assembly_entry (@{ $part->assemblies }) {
+ push @{ $data->{assembly_items}->[-1] }, { part => $assembly_entry->part, qty => $total_qty * $assembly_entry->qty };
+ $allocated += _calculate_assembly_item($self, $data, $assembly_entry->part, $total_qty * $assembly_entry->qty);
+ }
+
+ return $allocated;
+}
+
+sub _calculate_part_service_item {
+ my ($self, $data, $part, $total_qty, $base_factor) = @_;
+
+ $::lxdebug->message(0, "cpsi tq " . $total_qty);
+
+ return 0 unless $::eur && $data->{is_invoice} && $total_qty;
+
+ my ($entry);
+ $base_factor ||= 1;
+ my $remaining_qty = $total_qty;
+ my $expense_income_chart = $part->get_chart(type => $data->{is_sales} ? 'expense' : 'income', taxzone => $self->taxzone_id);
+ my $inventory_chart = $part->get_chart(type => 'inventory', taxzone => $self->taxzone_id);
+
+ my $iterator = SL::DB::Manager::InvoiceItem->get_all_iterator(query => [ and => [ parts_id => $part->id,
+ \'(base_qty + allocated) < 0' ] ]);
+
+ while (($remaining_qty > 0) && ($entry = $iterator->next)) {
+ my $qty = min($remaining_qty, $entry->base_qty * -1 - $entry->allocated - $data->{allocated}->{$part->id});
+ $::lxdebug->message(0, "qty $qty");
+
+ next unless $qty;
+
+ my $linetotal = _round(($entry->sellprice * $qty) / $base_factor, 2);
+
+ $data->{amounts_cogs}->{ $expense_income_chart->id } -= $linetotal;
+ $data->{amounts_cogs}->{ $inventory_chart->id } += $linetotal;
+
+ $data->{allocated}->{ $part->id } ||= 0;
+ $data->{allocated}->{ $part->id } += $qty;
+ $remaining_qty -= $qty;
+ }
+
+ $iterator->finish;
+
+ return $remaining_qty - $total_qty;
+}
+