Well I managed to get this working after a fashion.
I found 4 files where stock is adjusted -
ps_checkout.php
ps_order.php
ps_order_change.php
ps_order_edit.php
All are in -
\administrator\components\com_virtuemart\classes\
The last 2 are commented as - "...acts as a plugin for the order_print page"
so I have ignored them!
So in ps_checkout.php there is a function called "add" that "is the main function which stores the order information in the database."
Around line 1122 I found this -
// Update Stock Level and Product Sales, decrease - no matter if in stock or not!
$q = "UPDATE #__{vm}_product ";
$q .= "SET product_in_stock = product_in_stock - ".(int)$cart[$i]["quantity"];
$q .= " WHERE product_id = '" . $cart[$i]["product_id"]. "'";
$db->query($q);
$q = "UPDATE #__{vm}_product ";
$q .= "SET product_sales= product_sales + ".(int)$cart[$i]["quantity"];
$q .= " WHERE product_id='".$cart[$i]["product_id"]."'";
$db->query($q);
I commented the whole thing out, I don't want any stock adjusted here.
In ps_order.php there is a function called "order_status_update."
Around line 160 I found this -
// Do we need to re-update the Stock Level?
if( (strtoupper($d["order_status"]) == "X" || strtoupper($d["order_status"])=="R")
// && CHECK_STOCK == '1'
&& $curr_order_status != $d["order_status"]
) {
// Get the order items and update the stock level
// to the number before the order was placed
$q = "SELECT product_id, product_quantity FROM #__{vm}_order_item WHERE order_id='".$db->getEscaped($d["order_id"])."'";
$db->query( $q );
$dbu = new ps_DB;
// Now update each ordered product
while( $db->next_record() ) {
$q = "UPDATE #__{vm}_product SET product_in_stock=product_in_stock+".$db->f("product_quantity").", product_sales=product_sales-".$db->f("product_quantity")." WHERE product_id='".$db->f("product_id")."'";
$dbu->query( $q );
}
}
So this is restocking the item if the status is changed from anything to cancelled or refunded. Not really what I want so again I commented out the entire thing.
This is where I want the stock adjusted though so immediately after that I added this -
if( $curr_order_status!="C" && strtoupper($d["order_status"])=="C") { //going from anything to confirmed
$q = "SELECT product_id, product_quantity FROM #__{vm}_order_item WHERE order_id='".$db->getEscaped($d["order_id"])."'";
$db->query( $q );
$dbu = new ps_DB;
// Now update each ordered product
while( $db->next_record() ) {
$q = "UPDATE #__{vm}_product SET product_in_stock=product_in_stock-".$db->f("product_quantity").", product_sales=product_sales+".$db->f("product_quantity")." WHERE product_id='".$db->f("product_id")."'";
$dbu->query( $q );
}
}
This is reducing stock levels if the status is changed from anything to confirmed.
What has this achieved?
Now stock is only reduced when order status is changed to confirmed.
Stock is only increased when the order is removed from the system, on the order list page, select the order, click remove, stock is added back.
In reality, I don't think we will be removing orders to restock them, I think that will be done by hand.
This might prove problematic if we get a large number of orders, but Ill cross that bridge when I get to it.
There is only 1 of most of the items in my store so this works for me.
This does feel decidedly hacky, like I have probably missed something.
So feedback is welcome

Can you see any problems with what I've done?