/**
* Provides a data service to create base and demo data.
* Beware that most, if not all, base data is referenced by "Id" throughout the program.
* This allows changing the text of the 'name' property to something of the same meaning.
* But be sure to maintain the correct Id during creation, indicated by #1, #2 etc.
*/
class  CreateDataService {

    boolean transactional = false

    def authService
    def taskService
    def dateUtilService
    def appConfigService
    def assignedGroupService
    def assignedPersonService

/*******************************************
Start of Group methods.
Generally use these methods to create data.
*******************************************/

    /**
    * Always call this at startup to ensure that we have admin access
    * and that the system pseudo person is available.
    */
    def ensureSystemAndAdminAccess() {
        if(!Authority.findByAuthority("ROLE_AppAdmin") ) {
            log.warn "ROLE_AppAdmin not found, calling createAdminAuthority()."
            createAdminAuthority()
        }
        if(!Person.findByloginName("system") ) {
            log.warn "LoginName 'system' not found, calling createSystemPerson()."
            createSystemPerson()
        }
        if(!Person.findByloginName("admin") ) {
            log.warn "LoginName 'admin' not found, calling createAdminPerson()."
            createAdminPerson()
        }
    }

    /**
    * Create the base data required for the application to function.
    */
    def createBaseData() {

        if(appConfigService.exists("baseDataCreated")) {
            log.error "Base data has already been created, will NOT recreate."
            return false
        }

        log.info "Creating base data..."

        // Person and Utils
        createBaseAuthorities()
        createBasePersonGroups()
        createBaseDefinitions()
        createBaseUnitsOfMeasure()
        createBasePeriods()
        createBaseSupplierType()
        createBaseManufacturerType()

        // Tasks
        createBaseTaskGroups()
        createBaseTaskStatus()
        createBaseTaskPriorities()
        createBaseTaskBudgetStatus()
        createBaseTaskTypes()
        createBaseTaskModificationTypes()
        createBaseEntryTypes()

        // Inventory
        createBaseInventoryTypes()
        createBaseInventoryMovementTypes()

        // Assets
        createBaseExtenededAttributeTypes()
        createBaseMaintenancePolicies()

        // Record that data has been created.
        appConfigService.set("baseDataCreated")
    }

    /**
    * Create demo data for some example sites.
    */
    def createDemoData() {

        if(!appConfigService.exists("baseDataCreated")) {
            log.error "Demo data cannot be created until base data has been created."
            return false
        }

        if(appConfigService.exists("demoDataCreated")) {
            log.error "Demo data has already been created, will NOT recreate."
            return false
        }

        if(appConfigService.exists("demoDataCreationDisabled")) {
            log.error "Demo data creation has been disabled, will NOT create."
            return false
        }

        log.info "Creating demo data..."

        // Person and Utils
        createDemoPersons()
        createDemoSites()
        createDemoDepartments()
        createDemoSuppliers()
        createDemoManufacturers()

        // Tasks
        createDemoTasks()
        createDemoEntries()
        createDemoAssignedGroups()
        createDemoAssignedPersons()
        createDemoTaskRecurringSchedules()

        // Inventory
        createDemoInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
        createDemoInventoryLocations()
        createDemoInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
        createDemoInventoryItems()

        // Assets
        createDemoLifePlan()
        createDemoTaskProcedure()
        createDemoMaintenanceActions()
        createDemoSections()
        createDemoAssetTree()
        createDemoAssetExtenedAttributes()

        // Record that data has been created.
        appConfigService.set("demoDataCreated")
    }

/******************
Start of Person
*******************/

    def createAdminAuthority() {
        def authInstance

        // Authority #1
        authInstance = new Authority(description:"Application Admin, not required for daily use! Grants full admin access to the application.",
                                        authority:"ROLE_AppAdmin")
        saveAndTest(authInstance)
    }

    def createBaseAuthorities() {

        def authInstance

        // Authority #2
        authInstance = new Authority(description:"Business Manager, grants full management access.",
                                        authority:"ROLE_Manager")
        saveAndTest(authInstance)

        // Authority #3
        authInstance = new Authority(description:"Application User, all application users need this base role to allow login.",
                                        authority:"ROLE_AppUser")
        saveAndTest(authInstance)

        // Authority #4
        authInstance = new Authority(description:"Task Manager",
                                        authority:"ROLE_TaskManager")
        saveAndTest(authInstance)

        // Authority #5
        authInstance = new Authority(description:"Task User",
                                        authority:"ROLE_TaskUser")
        saveAndTest(authInstance)

        // Authority #6
        authInstance = new Authority(description:"Inventory Manager",
                                        authority:"ROLE_InventoryManager")
        saveAndTest(authInstance)

        // Authority #7
        authInstance = new Authority(description:"Inventory User",
                                        authority:"ROLE_InventoryUser")
        saveAndTest(authInstance)

        // Authority #8
        authInstance = new Authority(description:"Asset Manager",
                                        authority:"ROLE_AssetManager")
        saveAndTest(authInstance)

        // Authority #9
        authInstance = new Authority(description:"Asset User",
                                        authority:"ROLE_AssetUser")
        saveAndTest(authInstance)
    }

    void createBasePersonGroups() {
        //TypeOfPersonGroup
        def personGroupTypeInstance
            personGroupTypeInstance = new PersonGroupType(name:"Team")
        saveAndTest(personGroupTypeInstance)
            personGroupTypeInstance = new PersonGroupType(name:"Contractor")
        saveAndTest(personGroupTypeInstance)
            personGroupTypeInstance = new PersonGroupType(name:"ProjectTeam")
        saveAndTest(personGroupTypeInstance)

        //PersonGroup
        def personGroupInstance
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Electrical")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Mechanical")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Production")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(2),
                            name:"Kewl AirCon Guys")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(3),
                            name:"gnuMims")
        saveAndTest(personGroupInstance)
    }

    def createSystemPerson() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = authService.encodePassword(passClearText)
        def personInstance

        //Person #1
        personInstance = new Person(loginName:"system",
                                    firstName:"gnuMims",
                                    lastName:"System",
                                    description:'''This is a pseudo person that the application uses to insert data. DO NOT
                                                        assign login authorities or change the details of this person.''',
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"system@example.com")
        saveAndTest(personInstance)
    }

    def createAdminPerson() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = authService.encodePassword(passClearText)
        def personInstance

        //Person #2
        personInstance = new Person(loginName:"admin",
                                    firstName:"Admin",
                                    lastName:"Powers",
                                    description:'''Every time the application starts it ensures that the 'admin' login name is available.
                                                        DO update the password and other details but keep the login name as 'admin'. ''',
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"admin@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(1))
    }

    def createBasePersons() {
    }

    def createDemoPersons() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = authService.encodePassword(passClearText)
        def personInstance

        //Person #1 is system.
        //Person #2 is admin.

        //Person #3
        personInstance = new Person(loginName:"manager",
                                    firstName:"Demo",
                                    lastName:"Manager",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"manager@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(2))
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(5))

        //Person #4
        personInstance = new Person(loginName:"user",
                                    firstName:"Demo",
                                    lastName:"User",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToAuthorities(Authority.get(7))
        personInstance.addToAuthorities(Authority.get(9))
        personInstance.addToPersonGroups(PersonGroup.get(1))

        //Person #5
        personInstance = new Person(loginName:"craig",
                                    firstName:"Craig",
                                    lastName:"SuperSparky",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToAuthorities(Authority.get(7))
        personInstance.addToAuthorities(Authority.get(9))
        personInstance.addToPersonGroups(PersonGroup.get(1))

        //Person #6
        personInstance = new Person(loginName:"john",
                                    firstName:"John",
                                    lastName:"SuperFitter",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToAuthorities(Authority.get(7))
        personInstance.addToAuthorities(Authority.get(9))
        personInstance.addToPersonGroups(PersonGroup.get(2))

        //Person #7
        personInstance = new Person(loginName:"mann",
                                    firstName:"Production",
                                    lastName:"Mann",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToPersonGroups(PersonGroup.get(3))

        //Person #7
        personInstance = new Person(loginName:"testmanager",
                                    firstName:"Test",
                                    lastName:"Manager",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(4))
        personInstance.addToAuthorities(Authority.get(6))
        personInstance.addToAuthorities(Authority.get(8))
        personInstance.addToPersonGroups(PersonGroup.get(3))
    }

/***********************
START OF UTILITIES
***********************/

    //These can redefined by the site at deployment time.
    /// @todo: build an admin view so that only the value (definition) can be changed.
    def createBaseDefinitions() {
        appConfigService.set("Department Definition", "A department as recongised by accounting.")
        appConfigService.set("Site Definition", "The site, plant or area.")
        appConfigService.set("Section Definition", "A logical grouping of assets as determined by design.")
        appConfigService.set("Asset Definition", "Asset definition")
        appConfigService.set("Asset Sub Item 1 Name", "Asset Sub Item name")
        appConfigService.set("Asset Sub Item 1 Definition", "Asset Sub Item definition")
        appConfigService.set("Asset Sub Item 2 Name", "Asset Sub Item name")
        appConfigService.set("Asset Sub Item 2 Definition", "Asset Sub Item definition")
        appConfigService.set("Asset Sub Item 3 Name", "Asset Sub Item name")
        appConfigService.set("Asset Sub Item 3 Definition", "Asset Sub Item definition")
        appConfigService.set("Asset Sub Item 4 Name", "Asset Sub Item name")
        appConfigService.set("Asset Sub Item 4 Definition", "Asset Sub Item definition")
    }

    def createDemoSites() {
        //Site
        def siteInstance

        siteInstance = new Site(name: "Creek Mill")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "Jasper Street Depot")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "River Press")
        saveAndTest(siteInstance)
    }

    def createDemoDepartments() {

        //Department
        def departmentInstance

        //Department #1
        departmentInstance = new Department(name: "Print Centre",
                                                                                    site: Site.get(1))
        saveAndTest(departmentInstance)

        //Department #2
        departmentInstance = new Department(name: "Pulp Mill 2",
                                                                                    site: Site.get(2))
        saveAndTest(departmentInstance)
    }

    def createBaseUnitsOfMeasure() {

        //UnitOfMeasure
        def unitOfMeasureInstance

        //UnitOfMeasure #1
        unitOfMeasureInstance = new UnitOfMeasure(name: "each")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #2
        unitOfMeasureInstance = new UnitOfMeasure(name: "meter(s)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #3
        unitOfMeasureInstance = new UnitOfMeasure(name: "box(es)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #4
        unitOfMeasureInstance = new UnitOfMeasure(name: "litre(s)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #5
        unitOfMeasureInstance = new UnitOfMeasure(name: "kilogram(s)")
        saveAndTest(unitOfMeasureInstance)
    }

    def createBasePeriods() {

        //Period
        def periodInstance

        //Period #1
        periodInstance = new Period(period: "Day(s)")
        saveAndTest(periodInstance)

        //Period #2
        periodInstance = new Period(period: "Week(s)")
        saveAndTest(periodInstance)

        //Period #3
        periodInstance = new Period(period: "Month(s)")
        saveAndTest(periodInstance)

        //Period #4
        periodInstance = new Period(period: "Year(s)")
        saveAndTest(periodInstance)
    }

    def createBaseSupplierType() {

        // SupplierType
        def supplierTypeInstance

        // SupplierType #1
        supplierTypeInstance = new SupplierType(name: "OEM",
                                                                    description: "Original equipment supplier")
        saveAndTest(supplierTypeInstance)

        // SupplierType #2
        supplierTypeInstance = new SupplierType(name: "Local",
                                                                    description: "Local supplier")
        saveAndTest(supplierTypeInstance)
    }

    def createBaseManufacturerType() {

        // ManufacturerType
        def manufacturerTypeInstance

        // ManufacturerType #1
        manufacturerTypeInstance = new ManufacturerType(name: "OEM",
                                                                        description: "Original equipment manufacturer")
        saveAndTest(manufacturerTypeInstance)

        // ManufacturerType #2
        manufacturerTypeInstance = new ManufacturerType(name: "Alternate",
                                                                        description: "Not original equipment manufacturer")
        saveAndTest(manufacturerTypeInstance)

    }

    def createDemoSuppliers() {

        // Supplier
        def supplierInstance

        // Supplier #1
        supplierInstance = new Supplier(name: "OEM Distributors",
                                                                        supplierType: SupplierType.get(1))
        saveAndTest(supplierInstance)

        // Supplier #2
        supplierInstance = new Supplier(name: "Mex Holdings",
                                                                        supplierType: SupplierType.get(2))
        saveAndTest(supplierInstance)
    }

    def createDemoManufacturers() {

        // Manufacturer
        def manufacturerInstance

        // Manufacturer #1
        manufacturerInstance = new Manufacturer(name: "OEM Manufacturer",
                                                                        manufacturerType: ManufacturerType.get(1))
        saveAndTest(manufacturerInstance)

        // Manufacturer #2
        manufacturerInstance = new Manufacturer(name: "Laser Cutting Services Pty",
                                                                        manufacturerType: ManufacturerType.get(2))
        saveAndTest(manufacturerInstance)
    }

/*********************
START OF TASK
*********************/

    def createBaseTaskGroups() {
        //TaskGroup
        def taskGroupInstance

        //TaskGroup #1
        taskGroupInstance = new TaskGroup(name:"Engineering Activites",
                                                                            description:"Engineering daily activities")
        saveAndTest(taskGroupInstance)

        //TaskGroup #2
        taskGroupInstance = new TaskGroup(name:"Production Activites",
                                                                            description:"Production daily activities")
        saveAndTest(taskGroupInstance)

        //TaskGroup #3
        taskGroupInstance = new TaskGroup(name:"New Projects",
                                                                            description:" ")
        saveAndTest(taskGroupInstance)
    }

    def createBaseTaskStatus() {

        //TaskStatus
        def taskStatusInstance

        taskStatusInstance = new TaskStatus(name:"Not Started") // #1
        saveAndTest(taskStatusInstance)

        taskStatusInstance = new TaskStatus(name:"In Progress") // #2
        saveAndTest(taskStatusInstance)

        taskStatusInstance = new TaskStatus(name:"Complete") // #3
        saveAndTest(taskStatusInstance)
    }

    def createBaseTaskPriorities() {

        //TaskPriority
        def taskPriorityInstance

        taskPriorityInstance = new TaskPriority(name:"Normal") // #1
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"Low") // #2
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"High") // #3
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"Immediate") // #4
        saveAndTest(taskPriorityInstance)
    }

    def createBaseTaskBudgetStatus() {

        //TaskBudgetStatus
        def taskBudgetStatusInstance

        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Unplanned") // #1
        saveAndTest(taskBudgetStatusInstance)

        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Planned") // #2
        saveAndTest(taskBudgetStatusInstance)
    }

    def createBaseTaskTypes() {

        //TaskType
        def taskTypeInstance

        taskTypeInstance = new TaskType(name:"Unscheduled Breakin") // #1
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Preventative Maintenance") // #2
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Project") // #3
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Turnaround") // #4
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Production Run") // #5
        saveAndTest(taskTypeInstance)
    }

    def createBaseTaskModificationTypes() {

        //ModificationType
        def taskModificationTypeInstance
        taskModificationTypeInstance = new TaskModificationType(name:"Created").save()  // #1
        taskModificationTypeInstance = new TaskModificationType(name:"Started").save()  // #2
        taskModificationTypeInstance = new TaskModificationType(name:"Modified").save()  // #3
        taskModificationTypeInstance = new TaskModificationType(name:"Completed").save()  // #4
        taskModificationTypeInstance = new TaskModificationType(name:"Reopened").save()  // #5
        taskModificationTypeInstance = new TaskModificationType(name:"Trashed").save()  // #6
        taskModificationTypeInstance = new TaskModificationType(name:"Restored").save()  // #7
        taskModificationTypeInstance = new TaskModificationType(name:"Approved").save()  // #8
        taskModificationTypeInstance = new TaskModificationType(name:"Renege approval").save()  // #9
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Groups)").save()  // #10
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Persons)").save()  // #11
    }

    def createDemoTasks() {

        def taskResult
        def p = [:]

        //Task #1
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(2),
                description:"Check specific level sensor",
                comment:"Has been noted as problematic, try recalibrating.",
                targetStartDate: dateUtilService.today]

        taskResult = taskService.create(p)

        //Task #2
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(5),
                description:"Some follow-up work",
                comment:"Some help required",
                targetStartDate: dateUtilService.tomorrow,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #3
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(5),
                description:"A Sub Task can be created by setting the Parent Task value",
                comment:"Some help required",
                targetStartDate: dateUtilService.yesterday,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #4
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(2),
                 taskType:TaskType.get(1),
                 leadPerson:Person.get(4),
                 description:"Replace sensor at next opportunity.",
                 comment:"Nothing else has worked.",
                targetStartDate: dateUtilService.oneWeekFromNow,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #5
        p = [taskGroup:TaskGroup.findByName("Production Activites"),
                 taskPriority:TaskPriority.get(2),
                 taskType:TaskType.get(5),
                 leadPerson:Person.get(6),
                 description:"Production Report",
                 comment:"Production report for specific production run or shift",
                targetStartDate: dateUtilService.today - 6]

        taskResult = taskService.create(p)

        //Task #6
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(1),
                 taskType:TaskType.get(2),
                 leadPerson:Person.get(4),
                 description:"This is a recurring task",
                 comment:"If there is a parent task specified then this is a generated sub task, if there is a recurring schedule specified then this is a parent task.",
                targetStartDate: dateUtilService.today]

        taskResult = taskService.create(p)
    }

    def createBaseEntryTypes() {

        //EntryType
        def entryTypeInstance

        entryTypeInstance = new EntryType(name:"Fault") // #1
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Work Done") // #2
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Production Note") // #3
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Work Request") // #4
        saveAndTest(entryTypeInstance)
    }

    def createDemoEntries() {

        def entryResult
        def p = [:]

        //Entry #1
        p = [task: Task.get(1),
                entryType: EntryType.get(1),
                comment: "This level sensor is causing us trouble.",
                durationMinute: 20]

        entryResult = taskService.createEntry(p)

        //Entry #2
        p = [task: Task.get(1),
                entryType: EntryType.get(2),
                comment: "Cleaned sensor, see how it goes.",
                durationMinute: 30]

        entryResult = taskService.createEntry(p)

        //Entry #3
        p = [task: Task.get(1),
                entryType: EntryType.get(2),
                comment: "Checked up on it later and sensor is dropping out intermittently, created sub task to replace sensor.",
                durationMinute: 20]

        entryResult = taskService.createEntry(p)
    }

    def createDemoAssignedGroups() {

        def result
        def p = [:]

        //AssignedGroup #1
        p = [personGroup: PersonGroup.get(1),
                task: Task.get(1),
                estimatedHour: 2,
                estimatedMinute: 30]
        result = assignedGroupService.save(p)

        //AssignedGroup #2
        p = [personGroup: PersonGroup.get(2),
                task: Task.get(1),
                estimatedHour: 1,
                estimatedMinute: 0]
        result = assignedGroupService.save(p)
    }

    def createDemoAssignedPersons() {

        def result
        def p = [:]

        //AssignedPerson #1
        p = [person: Person.get(4),
                task: Task.get(1),
                estimatedHour: 1,
                estimatedMinute: 20]
        result = assignedPersonService.save(p)

        //AssignedPerson #2
        p = [person: Person.get(5),
                task: Task.get(1),
                estimatedHour: 3,
                estimatedMinute: 30]
        result = assignedPersonService.save(p)
    }

    def createDemoTaskRecurringSchedules() {

        //TaskRecurringSchedule
        def taskRecurringScheduleInstance

        //TaskRecurringSchedule #1
        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(1),
                                                                                                    recurEvery: 1,
                                                                                                    recurPeriod: Period.get(2),
                                                                                                    nextTargetStartDate: dateUtilService.today,
                                                                                                    generateAhead: 1,
                                                                                                    taskDuration: 2,
                                                                                                    taskDurationPeriod: Period.get(1),
                                                                                                    enabled: false)
        saveAndTest(taskRecurringScheduleInstance)

        //TaskRecurringSchedule #2
        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(6),
                                                                                                    recurEvery: 1,
                                                                                                    recurPeriod: Period.get(1),
                                                                                                    nextTargetStartDate: dateUtilService.today,
                                                                                                    generateAhead: 1,
                                                                                                    taskDuration: 1,
                                                                                                    taskDurationPeriod: Period.get(1),
                                                                                                    enabled: true)
        saveAndTest(taskRecurringScheduleInstance)
    }

/*************************
START OF INVENTORY
**************************/

    def createDemoInventoryStores() {

        //InventoryStore
        def inventoryStoreInstance

        inventoryStoreInstance = new InventoryStore(site: Site.get(1), name: "Store #1")
        saveAndTest(inventoryStoreInstance)

        inventoryStoreInstance = new InventoryStore(site: Site.get(2), name: "Store #2")
        saveAndTest(inventoryStoreInstance)
    }

    def createDemoInventoryLocations() {

        // InventoryLocation
        def inventoryLocation

        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(1), name: "A1-2")
        saveAndTest(inventoryLocation)

        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(1), name: "C55")
        saveAndTest(inventoryLocation)
    }

    def createDemoInventoryGroups() {

        //InventoryGroup
        def inventoryGroupInstance

        //InventoryGroup #1
        inventoryGroupInstance = new InventoryGroup(name: "Misc")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #2
        inventoryGroupInstance = new InventoryGroup(name: "Electrical")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #3
        inventoryGroupInstance = new InventoryGroup(name: "Mechanical")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #4
        inventoryGroupInstance = new InventoryGroup(name: "Production")
        saveAndTest(inventoryGroupInstance)
    }

    def createBaseInventoryTypes() {

        //InventoryType
        def inventoryTypeInstance

        inventoryTypeInstance = new InventoryType(name: "Consumable")
        saveAndTest(inventoryTypeInstance)

        inventoryTypeInstance = new InventoryType(name: "Repairable")
        saveAndTest(inventoryTypeInstance)
    }

    def createBaseInventoryMovementTypes() {

        // InventoryMovementType
        def inventoryMovementTypeInstance

        // InventoryMovementType #1
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Used",
                                                                                                                        incrementsInventory: false)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #2
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Repaired",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #3
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Purchase Received",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #4
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Increase",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #5
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Decrease",
                                                                                                                        incrementsInventory: false)
        saveAndTest(inventoryMovementTypeInstance)
    }

    def createDemoInventoryItems() {

        //InventoryItem
        def inventoryItemInstance

        //InventoryItem #1
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
                                                                                    inventoryLocation: InventoryLocation.get(1),
                                                                                    name: "Hemp rope",
                                                                                    description: "Natural hemp rope.",
                                                                                    unitsInStock: 2,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #2
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
                                                                                    inventoryLocation: InventoryLocation.get(1),
                                                                                    name: "Cotton Rope 12mm",
                                                                                    description: "A soft natural rope made from cotton.",
                                                                                    alternateItems: InventoryItem.get(1),
                                                                                    unitsInStock: 2,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #3
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "2305-2RS",
                                                                                    description: "Bearing 25x62x24mm double row self aligning ball",
                                                                                    unitsInStock: 3,
                                                                                    reorderPoint: 2)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #4
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(2),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "L1592-K10",
                                                                                    description: "10kW contactor",
                                                                                    unitsInStock: 4,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #5
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "6205-ZZ",
                                                                                    description: "Bearing 25x52x15mm single row ball shielded",
                                                                                    unitsInStock: 5,
                                                                                    reorderPoint: 2)
        saveAndTest(inventoryItemInstance)
    }

/*******************
START OF ASSET
*******************/

    def createDemoLifePlan() {

        //LifePlan
        def lifeplanInstance

        lifeplanInstance = new LifePlan(name: "Initial Plan")
        saveAndTest(lifeplanInstance)
    }

    def createBaseExtenededAttributeTypes() {

        //ExtendedAttributeType
        def extendedAttributeTypeInstance

        //ExtendedAttributeType #1
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Model Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #2
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Purchase Cost")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #3
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Serial Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #4
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufactured Date")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #5
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Location Description")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #6
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Centre")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #7
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Code")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #8
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufacturer's Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #9
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Inventory Number")
        saveAndTest(extendedAttributeTypeInstance)
    }

    def createBaseMaintenancePolicies() {

        //MaintenancePolicy
        def maintenancePolicyInstance

        //MaintenancePolicy #1
        maintenancePolicyInstance = new MaintenancePolicy(name: "Fixed Time")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #2
        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Online")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #3
        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Offline")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #4
        maintenancePolicyInstance = new MaintenancePolicy(name: "Design Out")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #5
        maintenancePolicyInstance = new MaintenancePolicy(name: "Operate To Failure")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #6
        maintenancePolicyInstance = new MaintenancePolicy(name: "Regulatory Requirement")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #7
        maintenancePolicyInstance = new MaintenancePolicy(name: "Hidden Function Test")
        saveAndTest(maintenancePolicyInstance)
    }

    def createDemoTaskProcedure() {

        //TaskProcedure
        def taskProcedureInstance

        taskProcedureInstance = new TaskProcedure(name: "Daily check")
        saveAndTest(taskProcedureInstance)
        taskProcedureInstance.addToTasks(Task.get(1))
    }

    def createDemoMaintenanceActions() {

        //MaintenanceAction
        def maintenanceActionInstance

        //MaintenanceAction #1
        maintenanceActionInstance = new MaintenanceAction(description: "Check all E-stops, activate E-stops S1-S12 and ensure machine cannot run",
                                                                                                        procedureStepNumber: 1,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)

        //MaintenanceAction #2
        maintenanceActionInstance = new MaintenanceAction(description: "Do more pushups",
                                                                                                        procedureStepNumber: 2,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)

        //MaintenanceAction #3
        maintenanceActionInstance = new MaintenanceAction(description: "Ok just one more pushup",
                                                                                                        procedureStepNumber: 3,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)
    }

    def createDemoSections() {

        //Section
        def sectionInstance

        //Section #1
        sectionInstance = new Section(name: "Press Section",
                                                                                    site: Site.get(3),
                                                                                    department: Department.get(1))
        saveAndTest(sectionInstance)

        //Section #2
        sectionInstance = new Section(name: "RO System",
                                                                                    site: Site.get(1),
                                                                                    department: Department.get(2))
        saveAndTest(sectionInstance)

        //Section #3
        sectionInstance = new Section(name: "Auxiliary Section",
                                                                                    site: Site.get(1),
                                                                                    department: Department.get(1))
        saveAndTest(sectionInstance)
    }

    def createDemoAssetTree() {

        //Asset
        def assetInstance

        //Asset #1
        def assetInstance1 = new Asset(name: "Print Tower 22",
                                                            section: Section.get(1))
        saveAndTest(assetInstance1)
//        assetInstance.addToMaintenanceActions(MaintenanceAction.get(1))

        //Asset #2
        def assetInstance2 = new Asset(name: "Print Tower 21",
                                                            section: Section.get(1))
        saveAndTest(assetInstance2)

        //Asset #3
        def assetInstance3 = new Asset(name: "Print Tower 23",
                                                            section: Section.get(1))
        saveAndTest(assetInstance3)

        //Asset #4
        def assetInstance4 = new Asset(name: "RO 1",
                                                            section: Section.get(2))
        saveAndTest(assetInstance4)

        //AssetSubItem
        def assetSubItemInstance

        //AssetSubItem #1 Level1
        def assetSubItemInstance1 = new AssetSubItem(name: "Print Tower")
        saveAndTest(assetSubItemInstance1)

        // Add assetSubItemInstance1 to some assets.
        assetInstance1.addToAssetSubItems(assetSubItemInstance1)
        assetInstance2.addToAssetSubItems(assetSubItemInstance1)
        assetInstance3.addToAssetSubItems(assetSubItemInstance1)

        //AssetSubItem #2 Level1
        def assetSubItemInstance2 = new AssetSubItem(name: "Reactor Tower")
        saveAndTest(assetSubItemInstance2)

        // Add assetSubItemInstance2 to some assets.
        assetInstance4.addToAssetSubItems(assetSubItemInstance2)

        //AssetSubItem #3 Level1
        def assetSubItemInstance3 = new AssetSubItem(name: "Blower Tower")
        saveAndTest(assetSubItemInstance3)

        // Add assetSubItemInstance3 to some assets.
        assetInstance4.addToAssetSubItems(assetSubItemInstance3)

        //AssetSubItem #4 Level2
        assetSubItemInstance = new AssetSubItem(name: "Print Unit Upper",
                                                                                parentItem: AssetSubItem.get(1))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #5 Level3
        assetSubItemInstance = new AssetSubItem(name: "Agitator",
                                                                                parentItem: AssetSubItem.get(2))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #6 Level2
        assetSubItemInstance = new AssetSubItem(name: "Scraper",
                                                                                parentItem: AssetSubItem.get(3))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #7 Level3
        assetSubItemInstance = new AssetSubItem(name: "Motor",
                                                                                parentItem: AssetSubItem.get(5))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #8 Level3
        assetSubItemInstance = new AssetSubItem(name: "Gearbox",
                                                                                parentItem: AssetSubItem.get(5))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #9 Level4
        assetSubItemInstance = new AssetSubItem(name: "DS Bearing",
                                                                                parentItem: AssetSubItem.get(7))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #10 Level4
        assetSubItemInstance = new AssetSubItem(name: "NDS Bearing",
                                                                                parentItem: AssetSubItem.get(7))
        saveAndTest(assetSubItemInstance)
    } // createDemoAssetTree()

    def createDemoAssetExtenedAttributes() {

        //AssetExtendedAttribute
        def assetExtendedAttributeInstance

        //AssetExtendedAttribute #1
        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "PU Mark 2",
                                                                                                                    asset: Asset.get(1),
                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(1))
        saveAndTest(assetExtendedAttributeInstance)

        //AssetExtendedAttribute #2
        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "On the far side of Tank 5",
                                                                                                                    asset: Asset.get(1),
                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(5))
        saveAndTest(assetExtendedAttributeInstance)
    }


/****************************************
Call this function instead of .save()
*****************************************/
    private boolean saveAndTest(object) {
        if(!object.save()) {
//             DemoDataSuccessful = false
            log.error "'${object}' failed to save!"
            log.error object.errors
            return false
        }
        return true
    }
}
