Index: /trunk/grails-app/i18n/messages.properties
===================================================================
--- /trunk/grails-app/i18n/messages.properties	(revision 963)
+++ /trunk/grails-app/i18n/messages.properties	(revision 964)
@@ -323,4 +323,5 @@
 inventoryItemPurchase.delete.failure.received.exists=Could not delete, items have been received.
 inventoryItemPurchase.delete.failure.payment.approved=Could not delete, payment has been approved.
+inventoryItemPurchase.delete.failure.reverse.move=Could not delete, associated movement could not be reversed, insufficient items in stock perhaps?
 inventoryItemPurchase.operation.not.permitted.on.inactive.or.obsolete.item=This operation is not permitted on an inactive or obsolete inventory item.
 inventoryItemPurchase.costCodes.not.found=No cost codes found, a person needs to be assigned to a purchasing group that has cost codes.
Index: /trunk/grails-app/services/InventoryMovementService.groovy
===================================================================
--- /trunk/grails-app/services/InventoryMovementService.groovy	(revision 963)
+++ /trunk/grails-app/services/InventoryMovementService.groovy	(revision 964)
@@ -9,4 +9,5 @@
         InventoryMovement.withTransaction { status ->
             def result = [:]
+            params =  params ?: [:]
 
             def fail = { Map m ->
@@ -20,5 +21,5 @@
             result.inventoryMovementInstance = InventoryMovement.lock(params.id)
 
-             if(!result.inventoryMovementInstance)
+            if(!result.inventoryMovementInstance)
                 fail(code:"default.not.found")
 
Index: /trunk/grails-app/services/InventoryPurchaseService.groovy
===================================================================
--- /trunk/grails-app/services/InventoryPurchaseService.groovy	(revision 963)
+++ /trunk/grails-app/services/InventoryPurchaseService.groovy	(revision 964)
@@ -194,7 +194,9 @@
                 }
 
-                def movementResult = inventoryMovementService.reverseMove(inventoryMovements[0])
-                if(movementResult.error)
-                    return fail(code:"inventoryMovement.quantity.insufficientItemsInStock")
+                if(inventoryMovements[0]) {
+                    def movementResult = inventoryMovementService.reverseMove(inventoryMovements[0])
+                    if(movementResult.error)
+                        return fail(code:"inventoryItemPurchase.delete.failure.reverse.move")
+                }
 
                 InventoryItemPurchase.withCriteria {
@@ -213,6 +215,20 @@
             // Deletion of received already requires payment approved to be deleted.
             if(purchaseTypeId == 1) {
+
                 def calcQuantities = calcQuantities(result.inventoryItemPurchaseInstance)
                 if(calcQuantities.totalReceived > 0)
+                    return fail(code:"inventoryItemPurchase.delete.failure.received.exists")
+
+                // Cover the case of 0 ordered and received.
+                // Only possible to have Received Complete (3L) in this case and not B/order (2L).
+                def receivedExists = InventoryItemPurchase.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem)
+                    eq("purchaseOrderNumber", result.inventoryItemPurchaseInstance.purchaseOrderNumber)
+                    inventoryItemPurchaseType {
+                            eq("id", 3L) // Received Complete.
+                    }
+                }
+
+                if(receivedExists)
                     return fail(code:"inventoryItemPurchase.delete.failure.received.exists")
             }
