-  # do stock
-  WH->transfer({
-    parts         => $self->part,
-    dst_bin       => $self->bin,
-    dst_wh        => $self->warehouse,
-    qty           => $::form->format_amount(\%::myconfig, $::form->{qty}),
-    unit          => $self->unit,
-    transfer_type => 'stock',
-    chargenumber  => $::form->{chargenumber},
-    ean           => $::form->{ean},
-    comment       => $::form->{comment},
-  });
-
-  if ($::form->{write_default_bin}) {
-    $self->part->bin($self->bin);
-    $self->part->warehouse($self->warehouse);
-    $self->part->save;
+  my $transfer_error;
+  my $qty = $::form->parse_amount(\%::myconfig, $::form->{qty});
+  if (!$qty) {
+    $transfer_error = t8('Cannot stock without amount');
+  } elsif ($qty < 0) {
+    $transfer_error = t8('Cannot stock negative amounts');
+  } else {
+    # do stock
+    $::form->throw_on_error(sub {
+      eval {
+        WH->transfer({
+          parts         => $self->part,
+          dst_bin       => $self->bin,
+          dst_wh        => $self->warehouse,
+          qty           => $qty,
+          unit          => $self->unit,
+          transfer_type => 'stock',
+          chargenumber  => $::form->{chargenumber},
+          bestbefore    => $::form->{bestbefore},
+          ean           => $::form->{ean},
+          comment       => $::form->{comment},
+        });
+        1;
+      } or do { $transfer_error = $EVAL_ERROR->getMessage; }
+    });
+
+    if (!$transfer_error) {
+      if ($::form->{write_default_bin}) {
+        $self->part->load;   # onhand is calculated in between. don't mess that up
+        $self->part->bin($self->bin);
+        $self->part->warehouse($self->warehouse);
+        $self->part->save;
+      }
+
+      flash_later('info', t8('Transfer successful'));
+    }