This is purposely designed functionality of Adempiere. Under some scenarios the Inventory is allowed to become negative because it is felt in those scenarios it is better to allow the process to complete but being negative it highlights a problem that must be addressed. In the case of the Internal Use the user is warned, that the stock will go negative if they proceed.
To change this standard functionality you need to modify the
org.compiere.model.MInventory.completeIt()
But if you change the code directly, it will make it more difficult to keep your version in sync with the base Adempiere or even just applying patches.
The recommended approach would be to add a Model Validator. This is a mechanism that watches the underlying data model and enables additional code/logic to be injected when a specific event occurs.
The event you want is the Document Event TIMING_BEFORE_COMPLETE.
You would create a new model validator as described in the link, register it in Adempiere's Application Dictionary and since you want your code to trigger when Inventory Document Type is executed you would add a method something like this
public String docValidate (PO po, int timing)
{
if (timing == TIMING_BEFORE_COMPLETE) {
if (po.get_TableName().equals(MInventory.Table_Name))
{
// your code to be executed
// it is executed just before any (internal or physical)
// Inventory is Completed
}
}
return null;
} // docValidate
A word of warning; the Internal Use functionality is the same used by Physical Inventory (i.e. a stock count) functionality! They just have different windows in Adempiere. So be sure to test both functionalities after any change is applied. From the core org.compiere.model.MInventory
there is a hint as how you might differentiate the two.
//Get Quantity Internal Use
BigDecimal qtyDiff = line.getQtyInternalUse().negate();
//If Quantity Internal Use = Zero Then Physical Inventory Else Internal Use Inventory
if (qtyDiff.signum() == 0)