• Michael Kolodner 13
  • NEWBIE
  • 50 Points
  • Member since 2015
  • Director of Information Systems
  • Spark

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 11
    Questions
  • 19
    Replies
I'm working on sandbox refresh code. For some reason, the portion of my test that makes sure I've inserted the task I want it not getting any code coverage. Here's my class:
global class SandboxRefreshScript implements SandboxPostCopy {
    global void runApexClass(SandboxContext context) {
        // Change value of Alias below to the Alias of user who should own the group
        // ensuring that it is unique among your users
        List<User> groupOwner = [SELECT Id, Username FROM User WHERE Alias = 'MKolo'];
        Id grpOwnerId = groupOwner[0].Id;
        
        // Create a Chatter Group for Payment Pipeline Changes
        List<CollaborationGroup> groups = new List<CollaborationGroup>();
        
        CollaborationGroup pipeline = new CollaborationGroup(
            CollaborationType = 'Public',
            Description = 'Group for showing changes to the cashflow pipeline. ',
            Name = 'Payment Pipeline Changes',
            OwnerId = grpOwnerId
        );
        groups.add(pipeline);
        
        //Create another Chatter Group for All Spark
        CollaborationGroup allSpark = new CollaborationGroup(
            CollaborationType = 'Public',
            Description = 'All Spark group. ',
            Name = 'All Spark',
            OwnerId = grpOwnerId
        );
        groups.add(allSpark);
        
        //Create another Chatter Group for Hiring Notifications
        CollaborationGroup hiringNotifications = new CollaborationGroup(
            CollaborationType = 'Private',
            Description = 'Hiring Notifications group. ',
            Name = 'Hiring Notifications',
            OwnerId = grpOwnerId
        );
        groups.add(hiringNotifications);
        
        insert groups;
        
        //Create a Task for yesterday (so it's immediately overdue) that
        //reminds to update Process Builders to use the new Chatter Groups.
        Task newTask = new Task(
        	Subject = 'Fix Process Builders',
            ActivityDate = Date.today()-1
        );
        insert newTask;

    }
}

And here's my test class:
@isTest
class TestSandboxRefreshScript {
    
    @isTest
    static void testMySandboxPrep() {
        
        Test.startTest();
        
        Test.testSandboxPostCopyScript(
            new SandboxRefreshScript(), UserInfo.getOrganizationId(),
            UserInfo.getOrganizationId(), UserInfo.getOrganizationName());
        
        Test.stopTest();
        
        // Test for Payment Pipeline Changes
        List<CollaborationGroup> chGroup = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'Payment Pipeline Changes'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Public', chGroup[0].CollaborationType, 'Chatter group is not public');
        
        // Test for All Spark
        List<CollaborationGroup> chGroup2 = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'All Spark'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Public', chGroup[0].CollaborationType, 'Chatter group is not public');
        
        // Test for Hiring Notifications
        List<CollaborationGroup> chGroup3 = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'Hiring Notifications'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Private', chGroup[0].CollaborationType, 'Chatter group is not private');
        
        //Test for Task Insert
        List<Task> tasks = [SELECT Id from Task WHERE ActivityDate = Yesterday];
        System.assertEquals(1, tasks.size(), 'Task Group List size not equal to 1');

    }
}

When I run the test,  there is no coverage for lines 41-45 and I don't understand why?
How can I take Today() and then get back, for example, the  next September 1 that will come?
Basically, if Today() returns 8/10/2019, I want to replace the month value with "9" and the day value with "1" but I don't know how to write it so that Apex will accept my manipulated XX/XX/XXXX as a date.
I'm trying to write a method that will take a date and give the fiscal year it's in. Here's my code, which compiles:
public class dateTest {

    public static string giveFY(date givenDate) {
    system.debug('givendate is ' + givenDate);    
    integer currentFiscalOrSchoolYear ;
        if (givenDate.Month() >= 7){
            currentFiscalOrSchoolYear = givenDate.Year() + 1;
        }
        else {
            currentFiscalOrSchoolYear = givenDate.Year();
        }
        system.debug('the month of givenDate is: ' + currentFiscalOrSchoolYear);
        //Get the last two digits
        string fy = (string.valueof(currentFiscalOrSchoolYear).right(2));
        system.debug('fy to be returned: ' + fy);
        return fy;
    }
	
}

But when I try to use this Execute Anonymous, I get an error "   Line: 2, Column: 16 Unexpected token '('.   "
system.debug('putting 2018-04-11 into dateTest');
dateTest.giveFY(2018-04-11);
system.debug('FY is: ' + fy);

system.debug('putting 2019-04-11 into dateTest');
dateTest.giveFY(2019-04-11);
system.debug('FY is: ' + fy);

 
I'm trying to build a class that will put data into my sandbox for testing and training. I'll put the code in below. When I ran it in Execute Anonymous the other day it all seemed to go fine. But today it only got part way. I got governer limit warnings (but not actually exceeding. Is there a difference?) Code is below. I imagine it's not the most efficient (I'm new at this), but I don't think it's bad. I'm on NPSP, so perhaps the NPSP triggers are having something to do with it?

Here's my class:
public class tempSparkTestDataUtil {
    

    //Method to get a single recordTypeId by inputting Object and Record Type Name (NOT API Name -- use spaces not underscores!)
    Public static Id recordTypeId(string obj, string recTypeName){
        Id recTypeId;
        if(obj!= null && recTypeName != null){
            recTypeId = Schema.getGlobalDescribe().get(obj).getDescribe().getRecordTypeInfosByName().get(recTypeName).getRecordTypeId();
            System.debug('Got record type id' + recTypeId + ' for object ' + obj + ' and record type name ' + recTypeName);
        }
        return recTypeId;  
    }
    
    //Gets the current year, gives last two digits for FY and SY usage
    public static string giveFY() {
        integer currentfiscalorschoolyear;
        if (Date.Today().Month() >= 7){
            currentfiscalorschoolyear = Date.Today().Year() + 1;
        }
        else {
            currentfiscalorschoolyear = Date.Today().Year();
        }
        //Get the last two digits
        string fy = (string.valueof(currentfiscalorschoolyear).right(2));
        return fy;
    }
    
    // Creates the Star Wars School District
    // This could be refactored to take a region and name so that you could use it to create other regions.
    public static Id createStarWarsSchoolDistrict(string region) {
        //Create a School District Account
        Account schoolDistrict = new Account (
            Name = 'Tatooine School District',
            School_Region__c = region,
            RecordTypeId = recordTypeId('Account', 'School District')
        );
        insert schoolDistrict;
        return schoolDistrict.Id;
    }
    
    //Creates Jedi Middle School
    // This could be refactored to take region, school name, and district name so you could use it to create multiple regions   
    public static Id createSchool(string region) {
        //Create a School on a School District
        Id district = createStarWarsSchoolDistrict(region);
        Account school = new Account (
            Name = 'Jedi Middle School',
            School_Region__c = region,
            School_District__c = district,
            RecordTypeId = recordTypeId('Account', 'Partner School')
        );
        insert school;
        return school.Id;
    }
    
    //Method to call create students
    //First calls school creation, which calls district creation, then puts four students with parents onto the school
    public static void createJediStudents() {
        //create school
        Id jediSchool = createSchool ('Star Wars (test data)');
        list <Contact> jediKids = new list <Contact>();
        
        Contact luke = new Contact (
            FirstName = 'Luke',
            LastName = 'Skywalker',
            Predicted_Graduation_Year_hs__c = String.ValueOf((Integer.ValueOf(giveFY())+2005)),
            Gender__c = 'Man',
            Race__c = 'MultiRacial',
            Birthdate = (Date.today()-(13*365)),
            Family_Application_Submitted__c = true,
            Date_of_Application__c = (Date.today() - 10),
            npsp__Primary_Affiliation__c = jediSchool,
            Parent_Consent_for_Evaluation__c = true,
            Date_of_parent_release_and_waiver__c = (Date.today() - 10),
            Release_Signed_By__c = 'Aunt Beroo',            
            Eval_Release_Signature__c = 'Aunt Beroo',
            Date_of_parent_evaluation_consent__c = (Date.today() - 10),
            Media_and_Photo_Release__c = true,
            Media_Release_Signature__c = 'Aunt Beroo',
            Date_of_parent_media_release__c = (Date.today() - 10),
            RecordTypeId = recordTypeId('Contact', 'Spark Student')
        );
        jediKids.add(luke);
        
        Contact leia = new Contact (
            FirstName = 'Princess Leia',
            LastName = 'Organa',
            Predicted_Graduation_Year_hs__c = String.ValueOf((Integer.ValueOf(giveFY())+2005)),
            Gender__c = 'Woman',
            Race__c = 'MultiRacial',
            Birthdate = (Date.today()-(13*365)),
            Family_Application_Submitted__c = true,
            Date_of_Application__c = (Date.today() - 10),
            npsp__Primary_Affiliation__c = jediSchool,
            Parent_Consent_for_Evaluation__c = true,
            Date_of_parent_release_and_waiver__c = (Date.today() - 10),
            Release_Signed_By__c = 'Queen Amidala',
            Eval_Release_Signature__c = 'Queen Amidala',
            Date_of_parent_evaluation_consent__c = (Date.today() - 10),
            Media_and_Photo_Release__c = true,
            Media_Release_Signature__c = 'Queen Amidala',
            Date_of_parent_media_release__c = (Date.today() - 10),
            RecordTypeId = recordTypeId('Contact', 'Spark Student')
        );
        jediKids.add(leia);
        
        Contact han = new Contact (
            FirstName = 'Han',
            LastName = 'Solo',
            Predicted_Graduation_Year_hs__c = String.ValueOf((Integer.ValueOf(giveFY())+2005)),
            Gender__c = 'Man',
            Race__c = 'MultiRacial',
            Birthdate = (Date.today()-(13*365)),
            Family_Application_Submitted__c = true,
            Date_of_Application__c = (Date.today() - 10),
            npsp__Primary_Affiliation__c = jediSchool,
            Parent_Consent_for_Evaluation__c = true,
            Date_of_parent_release_and_waiver__c = (Date.today() - 10),
            Release_Signed_By__c = 'Mrs. Solo',
            Eval_Release_Signature__c = 'Mrs. Solo',
            Date_of_parent_evaluation_consent__c = (Date.today() - 10),
            Media_and_Photo_Release__c = true,
            Media_Release_Signature__c = 'Mrs. Solo',
            Date_of_parent_media_release__c = (Date.today() - 10),
            RecordTypeId = recordTypeId('Contact', 'Spark Student')
        );
        jediKids.add(han);
        
        Contact chewie = new Contact (
            FirstName = 'Chewbacca',
            LastName = 'Wookie',
            Predicted_Graduation_Year_hs__c = String.ValueOf((Integer.ValueOf(giveFY())+2005)),
            Gender__c = 'Man',
            Race__c = 'MultiRacial',
            Birthdate = (Date.today()-(13*365)),
            Family_Application_Submitted__c = true,
            Date_of_Application__c = (Date.today() - 10),
            npsp__Primary_Affiliation__c = jediSchool,
            Parent_Consent_for_Evaluation__c = true,
            Date_of_parent_release_and_waiver__c = (Date.today() - 10),
            Release_Signed_By__c = 'Mama Wookie',
            Eval_Release_Signature__c = 'Mama Wookie',
            Date_of_parent_evaluation_consent__c = (Date.today() - 10),
            Media_and_Photo_Release__c = true,
            Media_Release_Signature__c = 'Mama Wookie',
            Date_of_parent_media_release__c = (Date.today() - 10),
            RecordTypeId = recordTypeId('Contact', 'Spark Student')
        );
        jediKids.add(chewie);
        
        Contact beroo = new Contact (
            FirstName = 'Aunt',
            LastName = 'Beroo',
            npsp__Primary_Affiliation__c = jediSchool,
            RecordTypeId = recordTypeId('Contact', 'Student Family Member')
        );
        jediKids.add(beroo);
        
        Contact amidala = new Contact (
            FirstName = 'Queen',
            LastName = 'Amidala',
            npsp__Primary_Affiliation__c = jediSchool,
            RecordTypeId = recordTypeId('Contact', 'Student Family Member')
        );
        jediKids.add(amidala);
        
        Contact wookie = new Contact (
            FirstName = 'Mrs.',
            LastName = 'Wookie',
            npsp__Primary_Affiliation__c = jediSchool,
            RecordTypeId = recordTypeId('Contact', 'Student Family Member')
        );
        jediKids.add(wookie);
        
        Contact solo = new Contact (
            FirstName = 'Mrs.',
            LastName = 'Solo',
            npsp__Primary_Affiliation__c = jediSchool,
            RecordTypeId = recordTypeId('Contact', 'Student Family Member')
        );
        jediKids.add(solo);
        
        insert jediKids;
        
        //need to loop through putting the parents onto the kids' records
        Id auntBeroo = [SELECT Id from Contact WHERE LastName = 'Beroo'].Id;
        Id queenAmidala = [SELECT Id from Contact WHERE LastName = 'Amidala'].Id;
        Id mrsWookie = [SELECT Id from Contact WHERE LastName = 'Wookie' AND FirstName = 'Mrs.'].Id;
        Id mrsSolo = [SELECT Id from Contact WHERE LastName = 'Solo' AND FirstName = 'Mrs.'].Id;
        
        Contact lukeCreated = [SELECT Id from Contact WHERE LastName = 'Skywalker'];
        Contact leiaCreated = [SELECT Id from Contact WHERE LastName = 'Organa'];
        Contact chewieCreated = [SELECT Id from Contact WHERE LastName = 'Wookie' AND FirstName = 'Chewbacca'];
        Contact hanCreated = [SELECT Id from Contact WHERE LastName = 'Solo' AND FirstName = 'Han'];
        
        lukeCreated.Primary_Parent__c = auntBeroo;
        update lukeCreated;
        leiaCreated.Primary_Parent__c = queenAmidala;
        update leiaCreated;
        hanCreated.Primary_Parent__c = mrsSolo;
        update hanCreated;
        chewieCreated.Primary_Parent__c = mrsWookie;
        update chewieCreated;
    }
    
    //Method to create a budget campaign hierarchy for the current FY    
    public static void createCampaignHierarchy(){
        string fy = giveFY();
        Campaign camptop = new Campaign (
            Name = ('Hierarchy Top FY' + fy),
            RecordTypeId = recordTypeId('Campaign', 'Parent Campaign')
        );
        insert camptop;
        
        List<Campaign> allcamps = new List<Campaign>();
        
        Campaign corpParts = new Campaign (
            Name = ('Corporate Partners FY'+ fy),
            ParentId = camptop.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(corpParts);
        
        Campaign indivs = new Campaign (
            Name = ('Individuals FY'+ fy),
            ParentId = camptop.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(indivs);
        
        Campaign schoolFees = new Campaign (
            Name = ('School Fees FY' + fy),
            ParentId = camptop.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(schoolFees);
        
        insert allcamps;
        
    }
    
    //Method to create a budget campaign hierarchy for the next FY    
    public static void createNextYrCampaignHierarchy(){
        integer nextfy =  Integer.ValueOf(giveFY())+1;
        string fytouse = string.valueOf(nextfy);
        
        Campaign camptopnextyr = new Campaign (
            Name = ('Hierarchy Top FY' + fytouse),
            RecordTypeId = recordTypeId('Campaign', 'Parent Campaign')
        );
        insert camptopnextyr;
        
        List<Campaign> allcamps = new List<Campaign>();
        
        Campaign corpParts = new Campaign (
            Name = ('Corporate Partners FY'+ fytouse),
            ParentId = camptopnextyr.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(corpParts);
        
        Campaign indivs = new Campaign (
            Name = ('Individuals FY'+ fytouse),
            ParentId = camptopnextyr.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(indivs);
        
        Campaign schoolFees = new Campaign (
            Name = ('School Fees FY' + fytouse),
            ParentId = camptopnextyr.Id,
            RecordTypeId = recordTypeId('Campaign', 'Primary Campaign')
        );
        allcamps.add(schoolFees);
        
        insert allcamps;
        
    }
    
    
    
    //Method to create two Accounts in Star Wars land, with two mentors on each.
    // This could be refactored to take region and a couple of contact names, then it could create companies in multiple regions.
    // To do this you'll also have to introduce some variable into contact and account names.
    // Another option to to leave this a method specific to Star Wars contacts. Then make a method for creating generic contacts with accounts.    
    public static void createStarWarsCompaniesWithMentors(){
        //Create Companies
        list <Account> accts = new list <Account>();
        
        Account acct1 = new Account (
            Name='Death Star Demolition',
            Account_Region__c = 'Star Wars (test data)',
            RecordTypeId = recordTypeId('Account', 'Corporate')
        );
        accts.add (acct1);
        
        Account acct2 = new Account (
            Name='Jedi Airlines',
            Account_Region__c = 'Star Wars (test data)',
            RecordTypeId = recordTypeId('Account', 'Corporate')
        );
        accts.add (acct2);
        
        insert accts;
        
        //Create Mentors on Companies
        list <Contact> mentors = new list <Contact>();
        Contact contact1 = new Contact (
            FirstName = 'Blasty',
            LastName = 'Explosion',
            Volunteer_Region__c = 'Star Wars (test data)',
            npsp__Primary_Affiliation__c = acct1.Id,
            Email = 'blasty@deathstar.com',
            Creativity__c = 2,
            Communication__c = 2,
            Following_directions__c = 1,
            Helping_Others__c = 3,
            Influencing_others__c = 3,
            Operating_Machines__c = 2,
            Planning__c = 2,
            Reading_and_Writing__c = 2,
            Research_and_Logic__c = 3,
            Singing_and_acting__c = 1,
            Solving_problems__c = 1,
            Understanding_Shapes__c = 3,
            Working_with_others__c = 1,
            Attention_to_detail__c = 1,
            Career_Area_Industry__c = 'Entertainment',
            RecordTypeId = recordTypeId('Contact', 'Individual')
        );
        mentors.add (contact1);
        
        Contact contact2 = new Contact (
            FirstName = 'Heroic',
            LastName = 'Knight',
            Volunteer_Region__c = 'Star Wars (test data)',
            npsp__Primary_Affiliation__c = acct2.Id,
            Email = 'hero@jedi.com',
            Creativity__c = 3,
            Communication__c = 2,
            Following_directions__c = 3,
            Helping_Others__c = 3,
            Influencing_others__c = 3,
            Operating_Machines__c = 1,
            Planning__c = 2,
            Reading_and_Writing__c = 2,
            Research_and_Logic__c = 1,
            Singing_and_acting__c = 1,
            Solving_problems__c = 1,
            Understanding_Shapes__c = 1,
            Working_with_others__c = 1,
            Attention_to_detail__c = 1,
            Career_Area_Industry__c = 'Entertainment',
            RecordTypeId = recordTypeId('Contact', 'Individual')
        );
        mentors.add (contact2);
        
        Contact contact3 = new Contact (
            FirstName = 'Smash',
            LastName = 'Stuff',
            Volunteer_Region__c = 'Star Wars (test data)',
            npsp__Primary_Affiliation__c = acct1.Id,
            Email = 'smash@deathstar.com',
            Creativity__c = 1,
            Communication__c = 1,
            Following_directions__c = 3,
            Helping_Others__c = 1,
            Influencing_others__c = 1,
            Operating_Machines__c = 3,
            Planning__c = 2,
            Reading_and_Writing__c = 2,
            Research_and_Logic__c = 3,
            Singing_and_acting__c = 1,
            Solving_problems__c = 1,
            Understanding_Shapes__c = 3,
            Working_with_others__c = 3,
            Attention_to_detail__c = 1,
            Career_Area_Industry__c = 'Entertainment',
            RecordTypeId = recordTypeId('Contact', 'Individual')
        );
        mentors.add (contact3);
        
        Contact contact4 = new Contact (
            FirstName = 'Wave',
            LastName = 'McLightsaber',
            Volunteer_Region__c = 'Star Wars (test data)',
            npsp__Primary_Affiliation__c = acct2.Id,
            Email = 'wave@jedi.com',
            Creativity__c = 3,
            Communication__c = 3,
            Following_directions__c = 3,
            Helping_Others__c = 3,
            Influencing_others__c = 3,
            Operating_Machines__c = 1,
            Planning__c = 1,
            Reading_and_Writing__c = 1,
            Research_and_Logic__c = 3,
            Singing_and_acting__c = 3,
            Solving_problems__c = 3,
            Understanding_Shapes__c = 1,
            Working_with_others__c = 1,
            Attention_to_detail__c = 1,
            Career_Area_Industry__c = 'Entertainment',
            RecordTypeId = recordTypeId('Contact', 'Individual')
        );
        mentors.add (contact4);
        
        insert mentors;
    }
    
    //Method to create the Star Wars Recruitment Campaigns for students and mentors
    public static void createStarWarsMentorRecruitCamp(){
        string sy = giveFY();
        List<Campaign> recruitCamps = new List<Campaign>();
        
        Campaign mentrec = new Campaign (
            Name = ('Star Wars (test) Mentor Recruitment Spring SY'+ sy),
            Type = 'Volunteer Recruitment',
            RecordTypeId = recordTypeId('Campaign', 'Mentor Recruitment'),
            School_Year__c = sy,
            Region__c = 'Star Wars (test)',
            Description = 'Mentor recruitment in the star wars region',
            Status = 'In Progress',
            StartDate = Date.today(),
            EndDate = Date.today()+180,
            IsActive = true
        );
        recruitCamps.add(mentrec);
        
        Campaign sturec = new Campaign (
            Name = ('Star Wars (test) Student Recruitment SY'+ sy),
            Type = 'Student Enrollment',
            RecordTypeId = recordTypeId('Campaign', 'Student Enrollment'),
            School_Year__c = sy,
            Region__c = 'Star Wars (test)',
            Description = 'student enrollment in the star wars region',
            Status = 'In Progress',
            StartDate = Date.today(),
            EndDate = Date.today()+180,
            IsActive = true
        );
        recruitCamps.add(sturec);
        
        insert recruitCamps;
        //in Prod, statuses are set by AAKonsult. Need the statuses of Qualified and Cleared on the campaign.
        List<CampaignMemberStatus> cms = new List<CampaignMemberStatus>();
        CampaignMemberStatus qual = new CampaignMemberStatus (
            CampaignID = mentrec.Id,
            Label = 'Qualified',
            HasResponded = true
        );
        CampaignMemberStatus clear = new CampaignMemberStatus (
            CampaignID = mentrec.Id,
            Label = 'Cleared',
            HasResponded = true
        );
        cms.add(clear);
        cms.add(qual);
        insert cms;
    }
    
    public static void createStarWarsPrograms(){
        List<yat__Program__c> progs = new List<yat__Program__c>();
        Campaign stuEnrollCamp = [SELECT Id FROM Campaign WHERE Name LIKE '%Star Wars (test) Student Recruitment SY%'];
        
        yat__Program__c labProg = new yat__Program__c (
            Name = ('Jedi Middle School Fall SY' + giveFY()),
            RecordTypeID = recordTypeId('yat__Program__c', 'Mentorship'),
            School__c = [SELECT Id FROM Account WHERE Name = 'Jedi Middle School'].Id,
            yat__Program_Season__c = 'Fall',
            yat__Program_Year__c = ('SY' + giveFY()),
            Student_Enrollment_Campaign__c = stuEnrollCamp.Id
        );
        progs.add(labProg);
        
        yat__Program__c mentorship = new yat__Program__c (
            Name = ('Jedi Middle School Spring SY' + giveFY()),
            RecordTypeID = recordTypeId('yat__Program__c', 'Spark Lab'),
            School__c = [SELECT Id FROM Account WHERE Name = 'Jedi Middle School'].Id,
            yat__Program_Season__c = 'Spring',
            yat__Program_Year__c = ('SY' + giveFY()),
            Student_Enrollment_Campaign__c = stuEnrollCamp.Id
        );
        progs.add(mentorship);
        
        yat__Program__c hspProg = new yat__Program__c (
            Name = ('Jedi Middle School HSP SY' + giveFY()),
            RecordTypeID = recordTypeId('yat__Program__c', 'HSP'),
            School__c = [SELECT Id FROM Account WHERE Name = 'Jedi Middle School'].Id,
            yat__Program_Year__c = ('SY' + giveFY()),
            Student_Enrollment_Campaign__c = stuEnrollCamp.Id
        );
        progs.add(hspProg);
        
        insert progs;

    }
    
    //Put mentors onto campaign in status Qualified. (This will create Catalog Entries for them because there is a Process Builder.)
    public static void putMentorsOnCampaign(){
        string mentorRecType = recordTypeId('Contact', 'Individual');
        list<Contact> mentors = [SELECT Id from Contact WHERE RecordTypeId = '%mentorRecType%'];
        system.debug('mentors are ' + mentors);
        Campaign mentEnrollCamp = [SELECT Id FROM Campaign WHERE Name LIKE '%Star Wars (test) Mentor Recruitment Spring SY%'];
        system.debug('campaign is ' + mentEnrollCamp);
        //you've got the list of mentors, now loop through putting them on the campaign
        list<CampaignMember> cMembers = new list<CampaignMember>();
        for (Contact currentMentor:mentors) {
            CampaignMember campMemb = new CampaignMember(
            	ContactId = currentMentor.Id,
                CampaignID = mentEnrollCamp.Id,
                Status = 'Qualified'
            );
            cMembers.add(campMemb);
        }
        system.debug('About to insert the list of campaign members, one for each mentor');
        insert cMembers;
    }
    
        //Put students onto campaign.
    public static void putStudentsOnCampaign(){
        string stuRecordType = recordTypeId('Contact', 'Spark Student');
        list<Contact> students = [SELECT Id from Contact WHERE RecordTypeId = '%stuRecordType%'];
        system.debug('students are ' + students);
        Campaign stuEnrollCamp = [SELECT Id FROM Campaign WHERE Name LIKE '%Star Wars (test) Student Recruitment SY%'];
        system.debug('campaign is ' + stuEnrollCamp);
        //you've got the list of students, now loop through putting them on the campaign
        list<CampaignMember> cStudents = new list<CampaignMember>();
        for (Contact currentStudent:students) {
            CampaignMember campMemb = new CampaignMember(
            	ContactId = currentStudent.Id,
                CampaignID = stuEnrollCamp.Id
            );
            cStudents.add(campMemb);
        }
        system.debug('About to insert the list of campaign members, one for each student');
        insert cStudents;
    }
    
    public static void putProgramOnCatEnts(){
        yat__Program__c prog = [SELECT Id from yat__Program__c WHERE Name LIKE '%Jedi Middle School Spring%' LIMIT 1];
        system.debug('prog is ' + prog);
        list<Catalog_Entry__c> catentsForProgs = [SELECT Id from Catalog_Entry__c];
        system.debug('catentsForProgs is ' + catentsForProgs);
        system.debug('About to update Assigned Programs on each catentForProg');
        for (Catalog_Entry__c currentCatEnt:catentsForProgs) {
            currentCatEnt.Assigned_Program__c = prog.Id;
            update currentCatEnt;
        }
    }
    
        public static void putMentorships(){
        string stuRecordType = recordTypeId('Contact', 'Spark Student');
        yat__Program__c prog = [SELECT Id from yat__Program__c WHERE Name LIKE '%Jedi Middle School Spring%' LIMIT 1];
        list<Contact> students = [SELECT Id, Full_Name__c, Spark_ID__c, npsp__Primary_Affiliation__c from Contact WHERE RecordTypeId = '%stuRecordType%'];
        system.debug('students are ' + students);
        list<Apprenticeship__c> apprents = new list<Apprenticeship__c>();
            for (Contact currentStudent:students) {
            Apprenticeship__c mentorship = new Apprenticeship__c(
            	Name = currentStudent.Full_Name__c + 'mentorship',
                School__c = currentStudent.npsp__Primary_Affiliation__c,
                Program__c = prog.Id,
                StageName__c = 'Student Requested',
                Creativity__c = 2,
                Attention_to_detail__c = 2,
                Communication__c = 3,
                Reading_and_Writing__c = 1,
                Planning__c = 3
            );
            apprents.add(mentorship);
        }
            insert apprents;
    }
}
And here's the execute anonymous I used to run it and create actual records:
tempSparkTestDataUtil.createJediStudents();
tempSparkTestDataUtil.createCampaignHierarchy();
tempSparkTestDataUtil.createNextYrCampaignHierarchy();
tempSparkTestDataUtil.createStarWarsCompaniesWithMentors();
tempSparkTestDataUtil.createStarWarsMentorRecruitCamp();
tempSparkTestDataUtil.createStarWarsPrograms();
tempSparkTestDataUtil.putMentorsOnCampaign();
tempSparkTestDataUtil.putStudentsOnCampaign();
tempSparkTestDataUtil.putProgramOnCatEnts();
tempSparkTestDataUtil.putMentorships();


 
Newbie to coding here and I'm trying to make a test class. Here's the code I've currently got:
@IsTest
public class tempTestPBchanges {
    
    /* Test class for making sure Assignment PB replacements are the same as the three PBs that existed before.
* Temporary, for use only in Dev sandbox, not to be deployed. If you want to save the code, copy it into a text file.
*/
    
    public static string createTestApprenticeship() {
        //------ Set up Test Data
        
        //Create a School District (may not be necessary, as school district is only required in the UI?)
        
        //Create a School
        Account testSchoolAccount = new Account(Name = 'Test school');
        insert testSchoolAccount;
        
        //Create a Company
        Account testCompanyAccount = new Account (Name='Test Company');
        insert testCompanyAccount;
        
        //Create a Mentor
        Contact testMentorContact = new Contact (
            npsp__Primary_Affiliation__c = testCompanyAccount.Id,
            FirstName = 'Test', 
            LastName = 'MentorOne',
            Creativity__c = 2,
            Communication__c = 2,
            Following_directions__c = 0,
            Helping_Others__c = 0,
            Influencing_others__c = 0,
            Operating_Machines__c = 0,
            Planning__c = 0,
            Reading_and_Writing__c = 0,
            Research_and_Logic__c = 0,
            Singing_and_acting__c = 0,
            Solving_problems__c = 0,
            Understanding_Shapes__c = 0,
            Working_with_others__c = 0,
            Attention_to_detail__c = 0,
            Career_Area_Industry__c = 'Entertainment'
        );
        insert testMentorContact;
        
        //Create a Catalog Entry
        Catalog_Entry__c testCatalogEntry1 = new Catalog_Entry__c(
            Name = 'Test MentorOne Catalog Entry', 
            Account__c = testCompanyAccount.Id,
            Primary_Mentor_Lookup__c = testMentorContact.Id
        );
        insert testCatalogEntry1;
        
        //Create a Student at the school
        Contact testStudentContact = new Contact (
            FirstName='Test', 
            LastName='Student', 
            npsp__Primary_Affiliation__c=testSchoolAccount.Id);
        insert testStudentContact;
        
        //Create a Program at the school
        yat__Program__c testProgram = new yat__Program__c(
            Name = 'Test Program SY19', 
            yat__Program_Year__c='SY19'
        );
        insert testProgram;
        
        //Create a Mentorship
        Apprenticeship__c testMentorship = new Apprenticeship__c(
            Name = 'Test Student Mentorship',
            Program__c = testProgram.Id,
            School__c = testSchoolAccount.Id,
            Student_Name__c = testStudentContact.Id,
            StageName__c = 'Student Requested',
            Creativity__c = 2,
            Communication__c = 2,
            Following_directions__c = 2,
            Helping_Others_New__c = 2,
            Influencing_others__c = 2,
            Operating_Machines__c = 2,
            Planning__c = 2,
            Reading_and_Writing__c = 2,
            Research_and_Logic__c = 2,
            Singing_and_acting__c = 2,
            Solving_problems__c = 2,
            Understanding_Shapes__c = 2,
            Working_with_others__c = 2,
            Attention_to_detail__c = 2,
            Innovative__c = 2,
            Creative__c = 2,
            Building__c = 2,
            Organization__c = 2,
            Scientific__c = 2,
            Social__c = 2
        );
        insert testMentorship;
        
        //------ Here ends the basic data creation
        
        //------ Testing the PBs
        //Create an Assignment
        Assignment_New__c testAssign = new Assignment_New__c (
            Name = 'testAssign',
            Catalogue_Entry__c = testCatalogEntry1.Id,
            Apprenticeship_Name__c = testMentorship.Id,
            Status__c = 'Possible Match'
        );
        insert testAssign;
        
    //Got to have a return for this method. Right now it's the assignment status. 
    //But it probably should be the Id so you can work with it later. But I can't make the system asserts work if it's an Id.        
        return testAssign.Status__c;
    }
    
    //Test 1: Assert that Assignment is not updated by the IsNew portions of the PB because it was not in the Matched Stage
    @isTest
    public static void testInsertAssignment() {
        String testAssignStatus = createTestApprenticeship();
        System.assertequals('Possible Match', testAssignStatus);
    }
Right now createTestApprenticeship() returns a string, the Status__c field of the inserted Assignment. But I would prefer to have it return an Id. Then in the test method I think I should be able to get the Status__c of that inserted Assignment by just using testAssignStatus.Status__c
But when I switch the return of the createTestApprenticeship() method to be Id, change the last line of that method to be 
return testAssign.Id;

and then change the system.assert to be
System.assertequals('Possible Match', testAssignStatus);
it won't compile. I get the error on that last line, in fact.

What am I missing, please?
I'm trying to write a class that will call a flow. I don't understand why Dev Console won't let me save, telling me that myFlow.start() is an invalid constructor name.
User-added image
I'm working on a method to take a phile of ContentDocumentLinks, find those that are linked to Expense__c, and then put those Expense__c records into a list. The bold line below won't compile with the error: Method does not exist or incorrect signature: void add(Id) from the type List<Expense__c>
I know this must be a simple fix, but help, please?

    //First attempted method:
    public list<Expense__c> Transformer(List<ContentDocumentLink> incomingcdls){
        //1. instantiate a list to hold the Expenses
        list<Expense__c> returnedexpenses = new list<Expense__c>();
        
        //2. Loop through the incoming CLDs. If the LinkedEntityID is that of an expense, add it to the list.
        for(ContentDocumentLink currentcdl : incomingcdls){
            if(currentcdl.LinkedEntityId.getSObjectType() == Schema.Expense__c.getSObjectType()){
               System.debug(currentcdl + ' was linked to a ' + currentcdl.LinkedEntityId.getSObjectType() + ' so it should go in the list.');
               //Now how to add it to the list? The below doesn't work
               returnedexpenses.add(currentcdl.LinkedEntityId);

            } else {
                System.debug(currentcdl + ' was linked to a ' + currentcdl.LinkedEntityId.getSObjectType() + ' so it should NOT go in the list.');
            }

    }
            
        //3. return the list of Expenses
        return returnedexpenses;
}
I've got a list of ContentDocumentLinks that's going to come from a trigger. (Or, in my current testing phase, is from this SOQL query:
ContentDocumentLink cdl : [Select Id, LinkedEntityId From ContentDocumentLink WHERE LinkedEntityId in ( SELECT Id FROM User)]

I need to loop through that and end up with a list of the LinkedEntityIds that are of a particular object. (In this case, a custom object Expenses__c.)

Help please?
Is there any way to put code directly into the client side controller for a Lightning Component (the .js file) to grab the base URL for my Salesforce instance? I have an idea that it's pretty simple using a server side class. But I am wondering if it can be done without that server side Apex class.
Is there a simple way, in the controller for a Lightning component, to get the My Domain of the org? I would like to easily know the URL for login of the org this component is displaying in so that I could know mydomain.my.salesforce.com or mydomain.lightning.force.com.

Literally all I'm looking for is the method to get the string "mydomain"
I'm trying to build a Lightning Component that I think should be very very simple. I understand that force:hasRecordID should allow a component that's on a Lightning Record Page to know the ID of the record being displayed. I, therefore, would like to take that ability to make a simple component that would show that record ID. (And before you ask, "Why not do it as a formula field?" The answer is that to do that I'd have to build a formula field on every object, whereas this component would be object agnostic. Plus it's a chance for me to learn a little about components...) I thought I could just use the string {!v.recordID}, but clearly I have to take some action to actually get the ID and put it into a variable. I don't know Javascript, so I'm stumped. But I know enough to know that someone who actually knew what they were doing could probably thew this together in seconds.

As I understand I, I think I should need only two things:

1. The component (.cmp)
The code I've got so far is:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="recordID" type="String" default="ID hasn't been set yet!"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <b>This is recordID {!v.recordID} </b>
</aura:component>

2. The controller (.js)
The code I've got for that so far is below. But I've been trying all sorts of things based on Googling and looking on Trailheads and the like, so this part could be way off:
({
    doInit : function(cmp) {
        var action = cmp.get("v.recordId");
        action.setCallback(this,function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                cmp.set("v.recordID", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})

Right now when I put the component on a page it just displays the text, but the string {!v.recordID} is replaced with the default text (or, when I didn't have that, just with nothing).

Help, please?
I'm working on sandbox refresh code. For some reason, the portion of my test that makes sure I've inserted the task I want it not getting any code coverage. Here's my class:
global class SandboxRefreshScript implements SandboxPostCopy {
    global void runApexClass(SandboxContext context) {
        // Change value of Alias below to the Alias of user who should own the group
        // ensuring that it is unique among your users
        List<User> groupOwner = [SELECT Id, Username FROM User WHERE Alias = 'MKolo'];
        Id grpOwnerId = groupOwner[0].Id;
        
        // Create a Chatter Group for Payment Pipeline Changes
        List<CollaborationGroup> groups = new List<CollaborationGroup>();
        
        CollaborationGroup pipeline = new CollaborationGroup(
            CollaborationType = 'Public',
            Description = 'Group for showing changes to the cashflow pipeline. ',
            Name = 'Payment Pipeline Changes',
            OwnerId = grpOwnerId
        );
        groups.add(pipeline);
        
        //Create another Chatter Group for All Spark
        CollaborationGroup allSpark = new CollaborationGroup(
            CollaborationType = 'Public',
            Description = 'All Spark group. ',
            Name = 'All Spark',
            OwnerId = grpOwnerId
        );
        groups.add(allSpark);
        
        //Create another Chatter Group for Hiring Notifications
        CollaborationGroup hiringNotifications = new CollaborationGroup(
            CollaborationType = 'Private',
            Description = 'Hiring Notifications group. ',
            Name = 'Hiring Notifications',
            OwnerId = grpOwnerId
        );
        groups.add(hiringNotifications);
        
        insert groups;
        
        //Create a Task for yesterday (so it's immediately overdue) that
        //reminds to update Process Builders to use the new Chatter Groups.
        Task newTask = new Task(
        	Subject = 'Fix Process Builders',
            ActivityDate = Date.today()-1
        );
        insert newTask;

    }
}

And here's my test class:
@isTest
class TestSandboxRefreshScript {
    
    @isTest
    static void testMySandboxPrep() {
        
        Test.startTest();
        
        Test.testSandboxPostCopyScript(
            new SandboxRefreshScript(), UserInfo.getOrganizationId(),
            UserInfo.getOrganizationId(), UserInfo.getOrganizationName());
        
        Test.stopTest();
        
        // Test for Payment Pipeline Changes
        List<CollaborationGroup> chGroup = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'Payment Pipeline Changes'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Public', chGroup[0].CollaborationType, 'Chatter group is not public');
        
        // Test for All Spark
        List<CollaborationGroup> chGroup2 = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'All Spark'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Public', chGroup[0].CollaborationType, 'Chatter group is not public');
        
        // Test for Hiring Notifications
        List<CollaborationGroup> chGroup3 = [SELECT Id, CollaborationType from CollaborationGroup WHERE Name = 'Hiring Notifications'];
        System.assertEquals(1, chGroup.size(), 'Chatter Group List size not equal to 1');
        System.assertEquals('Private', chGroup[0].CollaborationType, 'Chatter group is not private');
        
        //Test for Task Insert
        List<Task> tasks = [SELECT Id from Task WHERE ActivityDate = Yesterday];
        System.assertEquals(1, tasks.size(), 'Task Group List size not equal to 1');

    }
}

When I run the test,  there is no coverage for lines 41-45 and I don't understand why?
How can I take Today() and then get back, for example, the  next September 1 that will come?
Basically, if Today() returns 8/10/2019, I want to replace the month value with "9" and the day value with "1" but I don't know how to write it so that Apex will accept my manipulated XX/XX/XXXX as a date.
I'm trying to write a method that will take a date and give the fiscal year it's in. Here's my code, which compiles:
public class dateTest {

    public static string giveFY(date givenDate) {
    system.debug('givendate is ' + givenDate);    
    integer currentFiscalOrSchoolYear ;
        if (givenDate.Month() >= 7){
            currentFiscalOrSchoolYear = givenDate.Year() + 1;
        }
        else {
            currentFiscalOrSchoolYear = givenDate.Year();
        }
        system.debug('the month of givenDate is: ' + currentFiscalOrSchoolYear);
        //Get the last two digits
        string fy = (string.valueof(currentFiscalOrSchoolYear).right(2));
        system.debug('fy to be returned: ' + fy);
        return fy;
    }
	
}

But when I try to use this Execute Anonymous, I get an error "   Line: 2, Column: 16 Unexpected token '('.   "
system.debug('putting 2018-04-11 into dateTest');
dateTest.giveFY(2018-04-11);
system.debug('FY is: ' + fy);

system.debug('putting 2019-04-11 into dateTest');
dateTest.giveFY(2019-04-11);
system.debug('FY is: ' + fy);

 
Newbie to coding here and I'm trying to make a test class. Here's the code I've currently got:
@IsTest
public class tempTestPBchanges {
    
    /* Test class for making sure Assignment PB replacements are the same as the three PBs that existed before.
* Temporary, for use only in Dev sandbox, not to be deployed. If you want to save the code, copy it into a text file.
*/
    
    public static string createTestApprenticeship() {
        //------ Set up Test Data
        
        //Create a School District (may not be necessary, as school district is only required in the UI?)
        
        //Create a School
        Account testSchoolAccount = new Account(Name = 'Test school');
        insert testSchoolAccount;
        
        //Create a Company
        Account testCompanyAccount = new Account (Name='Test Company');
        insert testCompanyAccount;
        
        //Create a Mentor
        Contact testMentorContact = new Contact (
            npsp__Primary_Affiliation__c = testCompanyAccount.Id,
            FirstName = 'Test', 
            LastName = 'MentorOne',
            Creativity__c = 2,
            Communication__c = 2,
            Following_directions__c = 0,
            Helping_Others__c = 0,
            Influencing_others__c = 0,
            Operating_Machines__c = 0,
            Planning__c = 0,
            Reading_and_Writing__c = 0,
            Research_and_Logic__c = 0,
            Singing_and_acting__c = 0,
            Solving_problems__c = 0,
            Understanding_Shapes__c = 0,
            Working_with_others__c = 0,
            Attention_to_detail__c = 0,
            Career_Area_Industry__c = 'Entertainment'
        );
        insert testMentorContact;
        
        //Create a Catalog Entry
        Catalog_Entry__c testCatalogEntry1 = new Catalog_Entry__c(
            Name = 'Test MentorOne Catalog Entry', 
            Account__c = testCompanyAccount.Id,
            Primary_Mentor_Lookup__c = testMentorContact.Id
        );
        insert testCatalogEntry1;
        
        //Create a Student at the school
        Contact testStudentContact = new Contact (
            FirstName='Test', 
            LastName='Student', 
            npsp__Primary_Affiliation__c=testSchoolAccount.Id);
        insert testStudentContact;
        
        //Create a Program at the school
        yat__Program__c testProgram = new yat__Program__c(
            Name = 'Test Program SY19', 
            yat__Program_Year__c='SY19'
        );
        insert testProgram;
        
        //Create a Mentorship
        Apprenticeship__c testMentorship = new Apprenticeship__c(
            Name = 'Test Student Mentorship',
            Program__c = testProgram.Id,
            School__c = testSchoolAccount.Id,
            Student_Name__c = testStudentContact.Id,
            StageName__c = 'Student Requested',
            Creativity__c = 2,
            Communication__c = 2,
            Following_directions__c = 2,
            Helping_Others_New__c = 2,
            Influencing_others__c = 2,
            Operating_Machines__c = 2,
            Planning__c = 2,
            Reading_and_Writing__c = 2,
            Research_and_Logic__c = 2,
            Singing_and_acting__c = 2,
            Solving_problems__c = 2,
            Understanding_Shapes__c = 2,
            Working_with_others__c = 2,
            Attention_to_detail__c = 2,
            Innovative__c = 2,
            Creative__c = 2,
            Building__c = 2,
            Organization__c = 2,
            Scientific__c = 2,
            Social__c = 2
        );
        insert testMentorship;
        
        //------ Here ends the basic data creation
        
        //------ Testing the PBs
        //Create an Assignment
        Assignment_New__c testAssign = new Assignment_New__c (
            Name = 'testAssign',
            Catalogue_Entry__c = testCatalogEntry1.Id,
            Apprenticeship_Name__c = testMentorship.Id,
            Status__c = 'Possible Match'
        );
        insert testAssign;
        
    //Got to have a return for this method. Right now it's the assignment status. 
    //But it probably should be the Id so you can work with it later. But I can't make the system asserts work if it's an Id.        
        return testAssign.Status__c;
    }
    
    //Test 1: Assert that Assignment is not updated by the IsNew portions of the PB because it was not in the Matched Stage
    @isTest
    public static void testInsertAssignment() {
        String testAssignStatus = createTestApprenticeship();
        System.assertequals('Possible Match', testAssignStatus);
    }
Right now createTestApprenticeship() returns a string, the Status__c field of the inserted Assignment. But I would prefer to have it return an Id. Then in the test method I think I should be able to get the Status__c of that inserted Assignment by just using testAssignStatus.Status__c
But when I switch the return of the createTestApprenticeship() method to be Id, change the last line of that method to be 
return testAssign.Id;

and then change the system.assert to be
System.assertequals('Possible Match', testAssignStatus);
it won't compile. I get the error on that last line, in fact.

What am I missing, please?
I'm working on a method to take a phile of ContentDocumentLinks, find those that are linked to Expense__c, and then put those Expense__c records into a list. The bold line below won't compile with the error: Method does not exist or incorrect signature: void add(Id) from the type List<Expense__c>
I know this must be a simple fix, but help, please?

    //First attempted method:
    public list<Expense__c> Transformer(List<ContentDocumentLink> incomingcdls){
        //1. instantiate a list to hold the Expenses
        list<Expense__c> returnedexpenses = new list<Expense__c>();
        
        //2. Loop through the incoming CLDs. If the LinkedEntityID is that of an expense, add it to the list.
        for(ContentDocumentLink currentcdl : incomingcdls){
            if(currentcdl.LinkedEntityId.getSObjectType() == Schema.Expense__c.getSObjectType()){
               System.debug(currentcdl + ' was linked to a ' + currentcdl.LinkedEntityId.getSObjectType() + ' so it should go in the list.');
               //Now how to add it to the list? The below doesn't work
               returnedexpenses.add(currentcdl.LinkedEntityId);

            } else {
                System.debug(currentcdl + ' was linked to a ' + currentcdl.LinkedEntityId.getSObjectType() + ' so it should NOT go in the list.');
            }

    }
            
        //3. return the list of Expenses
        return returnedexpenses;
}
I've got a list of ContentDocumentLinks that's going to come from a trigger. (Or, in my current testing phase, is from this SOQL query:
ContentDocumentLink cdl : [Select Id, LinkedEntityId From ContentDocumentLink WHERE LinkedEntityId in ( SELECT Id FROM User)]

I need to loop through that and end up with a list of the LinkedEntityIds that are of a particular object. (In this case, a custom object Expenses__c.)

Help please?
Is there a simple way, in the controller for a Lightning component, to get the My Domain of the org? I would like to easily know the URL for login of the org this component is displaying in so that I could know mydomain.my.salesforce.com or mydomain.lightning.force.com.

Literally all I'm looking for is the method to get the string "mydomain"
I'm trying to build a Lightning Component that I think should be very very simple. I understand that force:hasRecordID should allow a component that's on a Lightning Record Page to know the ID of the record being displayed. I, therefore, would like to take that ability to make a simple component that would show that record ID. (And before you ask, "Why not do it as a formula field?" The answer is that to do that I'd have to build a formula field on every object, whereas this component would be object agnostic. Plus it's a chance for me to learn a little about components...) I thought I could just use the string {!v.recordID}, but clearly I have to take some action to actually get the ID and put it into a variable. I don't know Javascript, so I'm stumped. But I know enough to know that someone who actually knew what they were doing could probably thew this together in seconds.

As I understand I, I think I should need only two things:

1. The component (.cmp)
The code I've got so far is:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="recordID" type="String" default="ID hasn't been set yet!"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <b>This is recordID {!v.recordID} </b>
</aura:component>

2. The controller (.js)
The code I've got for that so far is below. But I've been trying all sorts of things based on Googling and looking on Trailheads and the like, so this part could be way off:
({
    doInit : function(cmp) {
        var action = cmp.get("v.recordId");
        action.setCallback(this,function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                cmp.set("v.recordID", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})

Right now when I put the component on a page it just displays the text, but the string {!v.recordID} is replaced with the default text (or, when I didn't have that, just with nothing).

Help, please?