class InventoryMovementService { boolean transactional = false def authService def authenticateService def reverseMove(params) { InventoryMovement.withTransaction { status -> def result = [:] params = params ?: [:] def fail = { Map m -> status.setRollbackOnly() if(result.inventoryMovementInstance && m.field) result.inventoryMovementInstance.errors.rejectValue(m.field, m.code) result.error = [ code: m.code, args: ["InventoryMovement", params.id] ] return result } result.inventoryMovementInstance = InventoryMovement.lock(params.id) if(!result.inventoryMovementInstance) fail(code:"default.not.found") // Fetch to prevent lazy initialization error. result.inventoryMovementInstance.inventoryItem.unitOfMeasure // Used type must have a task that is not complete or in the trash if(result.inventoryMovementInstance.inventoryMovementType.id == 1) { // Unlike move, if the task does not exist at all then deletion is still allowed. if(result.inventoryMovementInstance.task?.trash) return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash") if(result.inventoryMovementInstance.task?.taskStatus?.id == 3) return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask") // Check for authorisation on recurring tasks. if(result.inventoryMovementInstance.task?.taskRecurringSchedule) { if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager,ROLE_InventoryManager')) return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth") } } result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id) result.taskId = result.inventoryMovementInstance.task?.id if(!result.inventoryItemInstance) return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound") // Reverse the movement of inventory. if(!result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) { result.inventoryItemInstance.unitsInStock += result.inventoryMovementInstance.quantity } else { if(result.inventoryItemInstance.unitsInStock >= result.inventoryMovementInstance.quantity) { result.inventoryItemInstance.unitsInStock -= result.inventoryMovementInstance.quantity } else { return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock") } } if(!result.inventoryItemInstance.save()) return fail(code: "default.delete.failure") // Success.. result.inventoryMovementInstance.delete() return result } // end withTransaction } //end reverseMove() def move(params) { InventoryMovement.withTransaction { status -> def result = [:] def fail = { Map m -> status.setRollbackOnly() if(result.inventoryMovementInstance && m.field) result.inventoryMovementInstance.errors.rejectValue(m.field, m.code) result.error = [ code: m.code, args: ["InventoryMovement", params.id] ] return result } result.inventoryMovementInstance = new InventoryMovement(params) result.inventoryMovementInstance.person = authService.currentUser // Fetch to prevent lazy initialization error. result.inventoryMovementInstance.inventoryItem.unitOfMeasure // Used type must have a task that is not complete or in the trash if(result.inventoryMovementInstance.inventoryMovementType.id == 1) { if(!result.inventoryMovementInstance.task) return fail(field:"task", code:"task.notFound") if(result.inventoryMovementInstance.task.trash) return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash") if(result.inventoryMovementInstance.task.taskStatus.id == 3) return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask") // Check for authorisation on recurring tasks. if(result.inventoryMovementInstance.task.taskRecurringSchedule) { if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager,ROLE_InventoryManager')) return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth") } } // Bail early if validation fails. if(!result.inventoryMovementInstance.validate()) return fail(code:"default.create.failure") def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id) result.taskId = result.inventoryMovementInstance.task?.id if(!inventoryItem) return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound") // Perform the movement of inventory. if(result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) { inventoryItem.unitsInStock += result.inventoryMovementInstance.quantity } else { if(inventoryItem.unitsInStock >= result.inventoryMovementInstance.quantity) { inventoryItem.unitsInStock -= result.inventoryMovementInstance.quantity } else { return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock") } } if(!inventoryItem.save() || !result.inventoryMovementInstance.save()) return fail(code:"default.create.failure") // Success.. return result } // end withTransaction } // end move() } // end class