/** * Provides a service class for the TaskProcedure domain class. */ class TaskProcedureService { boolean transactional = false def authService def dateUtilService /** * Updates an existing taskProcedure. * @param params The params to update for taskProcedure with id of params.id. * @returns A map containing result.error (if any error) and result.taskProcedureInstance (if available). */ def update(params) { TaskProcedure.withTransaction { status -> def result = [:] def fail = { Map m -> status.setRollbackOnly() if(result.taskProcedureInstance && m.field) result.taskProcedureInstance.errors.rejectValue(m.field, m.code) result.error = [ code: m.code, args: ["TaskProcedure", params.id] ] // Fetch to prevent lazy initialization error. result.taskProcedureInstance.revisions.each {it.createdBy.toString()} return result } result.taskProcedureInstance = TaskProcedure.get(params.id) if(!result.taskProcedureInstance) return fail(code:"default.not.found") // Optimistic locking check. if(params.version) { if(result.taskProcedureInstance.version > params.version.toLong()) return fail(field:"version", code:"default.optimistic.locking.failure") } result.taskProcedureInstance.properties = params // Gaps in the html index's can be created by adding 2 items and removing the first one. // This creates a gap at the missing index where LazyList will return a null. def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it} if (nullMaintenanceActions) { result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions) } def nullDocumentReferences = result.taskProcedureInstance.documentReferences.findAll {!it} if (nullDocumentReferences) { result.taskProcedureInstance.documentReferences.removeAll(nullDocumentReferences) } // Save for restoration if validation fails. def savedMaintenanceActions = new ArrayList(result.taskProcedureInstance.maintenanceActions) def savedDocumentReferences = new ArrayList(result.taskProcedureInstance.documentReferences) // Remove toBeDeleted before validation. def ma_toBeDeleted = result.taskProcedureInstance.maintenanceActions.findAll {it.toBeDeleted} if (ma_toBeDeleted) { result.taskProcedureInstance.maintenanceActions.removeAll(ma_toBeDeleted) } def docRef_toBeDeleted = result.taskProcedureInstance.documentReferences.findAll {it.toBeDeleted} if (docRef_toBeDeleted) { result.taskProcedureInstance.documentReferences.removeAll(docRef_toBeDeleted) } if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) { // Restore the saved items, some of which contain toBeDeleted flags but // have not been deleted yet since validation failed. // The toBeDeleted items are hidden in the view. result.taskProcedureInstance.maintenanceActions = savedMaintenanceActions result.taskProcedureInstance.documentReferences = savedDocumentReferences // Populate collection errors for display. result.taskProcedureInstance.maintenanceActions.each { it.validate() } result.taskProcedureInstance.documentReferences.each { it.validate() } return fail(code:"default.update.failure") } // Sort MaintenanceActions. result.taskProcedureInstance.maintenanceActions.sort { p1, p2 -> p1.procedureStepNumber <=> p2.procedureStepNumber } def r = createRevision(result.taskProcedureInstance) if(r.error) return fail(field:'id', code:"default.create.revision.failure") // Also sets: taskInstance.taskProcedureRevision = taskProcedureRevision r.taskProcedureRevision.addToTasks(result.taskProcedureInstance.linkedTask) // Update tasks that are using previousRevision. // Only those that are not started and due to be started today or in the future. def previousRevision = result.taskProcedureInstance.getRevision(r.taskProcedureRevision.revision - 1) if(previousRevision) { Task.withCriteria { eq("taskProcedureRevision", previousRevision) ge("targetStartDate", dateUtilService.today) taskStatus { idEq(1L) // Not Started. } maxResults(10000) }.each { it.taskProcedureRevision = r.taskProcedureRevision } } // Success. return result } // end withTransaction } // end update() /** * Creates a new taskProcedure with the given params. * @param params The params to use when creating the new taskProcedure. * @returns A map containing result.error (if any error) and result.taskProcedure. */ def save(params) { def result = [:] TaskProcedure.withTransaction { status -> def fail = { Map m -> status.setRollbackOnly() if(result.taskProcedureInstance && m.field) result.taskProcedureInstance.errors.rejectValue(m.field, m.code) result.error = [ code: m.code, args: ["TaskProcedure", params.id] ] // Fetch to prevent lazy initialization error. result.taskProcedureInstance.linkedTask.primaryAsset return result } result.taskProcedureInstance = new TaskProcedure(params) // Optimistic locking check on linkedTask. if(result.taskProcedureInstance.linkedTask.taskProcedureRevision) return fail(field:"version", code:"default.optimistic.locking.failure") // Gaps in the html index's can be created by adding 2 items and removing the first one. // This creates a gap at the missing index where LazyList will return a null. def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it} if (nullMaintenanceActions) { result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions) } def nullDocumentReferences = result.taskProcedureInstance.documentReferences.findAll {!it} if (nullDocumentReferences) { result.taskProcedureInstance.documentReferences.removeAll(nullDocumentReferences) } if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) { // Populate collection errors for display. result.taskProcedureInstance.maintenanceActions.each { it.validate() } result.taskProcedureInstance.documentReferences.each { it.validate() } return fail(code:"default.create.failure") } // Sort MaintenanceActions. result.taskProcedureInstance.maintenanceActions.sort { p1, p2 -> p1.procedureStepNumber <=> p2.procedureStepNumber } def r = createRevision(result.taskProcedureInstance) if(r.error) return fail(field:'id', code:"default.create.revision.failure") // Also sets: taskInstance.taskProcedureRevision = taskProcedureRevision r.taskProcedureRevision.addToTasks(result.taskProcedureInstance.linkedTask) } // end withTransaction // Success. return result } // end save() /** * Creates a new taskProcedureRevision. * @param taskProcedureInstance The taskProcedure to create the revision for. * @returns A map containing result.error (if any error) and result.taskProcedureRevision. */ def createRevision(taskProcedureInstance) { def result = [:] TaskProcedureRevision.withTransaction { status -> def fail = { Map m -> status.setRollbackOnly() if(result.taskProcedureRevision && m.field) result.taskProcedureRevision.errors.rejectValue(m.field, m.code) result.error = [ code: m.code, args: ["TaskProcedureRevision"] ] return result } result.taskProcedureRevision = new TaskProcedureRevision() taskProcedureInstance.addToRevisions(result.taskProcedureRevision) result.taskProcedureRevision.taskProcedure = taskProcedureInstance result.taskProcedureRevision.linkedTask = taskProcedureInstance.linkedTask result.taskProcedureRevision.createdBy = authService.currentUser result.taskProcedureRevision.revision = 0 // init to prevent DataIntegrityViolationException result.taskProcedureRevision.revision = taskProcedureInstance.revision taskProcedureInstance.maintenanceActions.each { result.taskProcedureRevision.addToMaintenanceActions(new MaintenanceAction(it.properties)) } taskProcedureInstance.documentReferences.each { result.taskProcedureRevision.addToDocumentReferences(new DocumentReference(it.properties)) } if(result.taskProcedureRevision.hasErrors() || !result.taskProcedureRevision.save()) { log.error result.taskProcedureRevision.errors return fail(code:"default.create.failure") } } // end withTransaction // Success. return result } // end createRevision() } // end class