+sub calc_qtys {
+  my ($self, $orderitems) = @_;
+  # using $orderitem->shipped_qty 40 times is far too slow. need to do it manually
+  #
+
+  return unless scalar @$orderitems;
+
+  my %orderitems_by_id = map { $_->id => $_ } @$orderitems;
+
+  my $query = $self->use_linked_items ? _calc_qtys_query_linked_items(scalar @$orderitems)
+            :                           _calc_qtys_query_match_parts(scalar @$orderitems);
+
+  my $result = SL::DBUtils::selectall_hashref_query($::form, $::form->get_standard_dbh, $query, map { $_->id } @$orderitems);
+
+  for my $row (@$result) {
+    my $item = $orderitems_by_id{ $row->{id} };
+    $item->{shipped_qty}   ||= 0;
+    $item->{delivered_qty} ||= 0;
+    $item->{shipped_qty}    += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty};
+    $item->{delivered_qty}  += AM->convert_unit($row->{unit} => $item->unit) * $row->{qty} if $row->{delivered};
+  }
+}
+
+sub _calc_qtys_query_match_parts {
+  my ($num_items) = @_;
+
+  my $query = <<SQL;
+    SELECT oi.id, doi.qty, doi.unit, doe.delivered
+    FROM record_links rl
+    INNER JOIN delivery_order_items doi ON (doi.delivery_order_id = rl.to_id)
+    INNER JOIN delivery_orders doe ON (doe.id = rl.to_id)
+    INNER JOIN orderitems oi ON (oi.trans_id = rl.from_id)
+    WHERE rl.from_table = 'oe'
+      AND rl.to_table   = 'delivery_orders'
+      AND oi.parts_id   = doi.parts_id
+      AND oi.id IN (@{[ join ', ', ("?")x $num_items ]})
+SQL
+
+  return $query;
+}
+
+sub _calc_qtys_query_linked_items {
+  my ($num_items) = @_;
+
+  my $query = <<SQL;
+    SELECT rl.from_id as id, doi.qty, doi.unit, doe.delivered
+    FROM record_links rl
+    INNER JOIN delivery_order_items doi ON (doi.id = rl.to_id)
+    INNER JOIN delivery_orders doe ON (doe.id = doi.delivery_order_id)
+    WHERE rl.from_table LIKE 'orderitems'
+      AND rl.to_table   LIKE 'delivery_order_items'
+      AND rl.from_id IN (@{[ join ', ', ("?")x $num_items ]})
+SQL
+
+  return $query;
+}
+