• Stuart HARRISON
  • NEWBIE
  • 40 Points
  • Member since 2018

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 5
    Questions
  • 15
    Replies
I have an Apex class that runs based on a database enquiry and creates new opportunities (clones) where certain criteria are met. Im unsure how to build a test script for this ? Ive done all my testing in sandbox by running through the developer portal. For pushing to Production I now need a test script. I dont want loads of new opportunities created in production so Im not sure how I do this ? My Apex code is below. Any pointers appreciated 0 its my first Apex Class change.

global class CreateRenewal implements Schedulable { 
    global void execute(SchedulableContext ctx) { 

        List<Opportunity> InList = [Select 
        AccountID,
        Amount,
        CloseDate,
        CreatedByID,
        Description,
        ExpectedRevenue,
        ForecastCategoryName,
        LeadSource,
        NextStep,
        CurrencyIsoCode,
        Name,
        OwnerID,
        RecordTypeID,
        Pricebook2ID,
        CampaignID,
        IsPrivate,
        Probability,
        TotalOpportunityQuantity,
        IqScore,
        StageName,
        Type,
        Compliance__c,
        Coverholder_Commission__c,
        Local_Insurer_Commission__c,
        Local_Taxes__c,
        Reinsurance_broker_commission__c,
        Retail_broker_commission__c,
        Sum_Insured__c,
        Account_Contact__c,
        Additional_Amount_in_Oppty_Currency__c,
        Additional_Countries__c,
        Additional_tax_commission_cost_descripti__c,
        AXA_ASR_Pricing_Model_Version__c,
        Business_Type_Class__c,
        Cedents_retention__c,
        Cedents_Retention_Amount__c,
        Channel__c,
        Coinsurances_Commissions_from_Brokers__c,
        Coinsurances_Commissions_to_Brokers__c,
        Coinsurances_Commissions_to_Coverholder__c,
        Coinsurances_Percentage__c,
        Coinsurances_Premium__c,
        Contract_Type__c,
        Coverholder__c,
        Days_to_Quote_Released__c,
        DB_Competitor__c,
        Direct_Contact__c,
        Direct_Source__c,
        Estimated_S6130_GNP__c,
        Fast_track__c,
        Global_GNP__c,
        Insured_Period_From__c,
        Insured_Period_To__c,
        Intermediary_Commission__c,
        Intermediary_Account__c,
        Intermediary_Contact__c,
        Intermediary_Reinsurance_Broker__c,
        Intermediary_Reinsurance_Contact__c,
        Layer__c,
        LoB__c,
        Local_Insurer__c,
        Local_Insurer_Commission_Percentage__c,
        Local_Insurer_Contact__c,
        Lost_Cancel_Reason__c,
        Lost_Cancelled_Reason_Comment__c,
        Lost_Due_to_Pricing_amount__c,
        Lost_Due_to_Pricing_currency__c,
        Non_Renewable__c,
        Opportunity_Channel__c,
        P_Coverholder_Commission__c,
        P_Intermediary_Commission__c,
        P_Local_Insurer_Commission__c,
        P_Local_Taxes__c,
        Policy__c,
        Post_Underwriting_Compliance__c,
        Pre_Issue_Compliance__c,
        Pre_Underwriting_Compliance__c,
        Previously_won_or_lost__c,
        Pricing_Model_Source__c,
        Primary_Country__c,
        Proportional__c,
        P_Syndicate_Gross_Premium__c,
        P_Syndicate_Premium__c,
        Quote_Released_Date__c,
        Reinsurance_Facultative__c,
        Reinsurer_Taxes__c,
        Reinsurer_Taxes_Amount__c,
        Renewal_Created__c,
        Renewal_Indicator__c,
        Renewal_Information__c,
        Rest_of_World__c,
        reviewScope__c,
        Risk_Category__c,
        AXA_GNP__c,
        S1084_S6130_Percentage__c,
        S6130_Coverholder_Commission__c,
        S6130_Coverholder_Commission_Amount__c,
        Syndicate_GGP__c,
        S6130_Line_Size__c,
        S6130_Local_Insurer_Commission__c,
        S6130_Local_Insurer_Commission_Amount__c,
        S6130_Local_Taxes__c,
        S6130_Local_Taxes_Amount__c,
        Syndicate_Percentage__c,
        S6130_Reinsurance_Broker_Commission__c,
        S6130_Reinsurance_Broker_Commission_Amou__c,
        S6130_Retail_Broker_Commission__c,
        S6130_Retail_Broker_Commission_Amount__c,
        Short_Name__c,
        Step__c,
        Subject_to_NDA__c,
        Sub_Status__c,
        Underwriter__c,
        UW_Reference__c,
        Renewed_Opportunity_Link__c,
        Renewal_Opportunity_Link__c,
        Renewal_Opportunity__c
        
        From Opportunity 
        where Opportunity.Insured_Period_to__c <= NEXT_90_DAYS 
        AND Opportunity.LoB__c = 'Property'
        AND Opportunity.Insured_Period_to__c > :date.today()
        AND Opportunity.Renewal_Created__c != 'YES'
        AND (opportunity.StageName = 'Closed - Won' OR opportunity.StageName = 'Closed - Lost')]; 
        
        
        List<Opportunity> newOpps=new List<Opportunity>();

        for(Opportunity c: InList){
        
    if (c.StageName == 'Closed - Won'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.Short_name__c = c.Short_name__c;
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Won';
            Opp.Renewed_Opportunity_Link__c = c.Id;
            Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
            newOpps.add(Opp);
            c.Renewal_Opportunity_Link__c = opp.Id;
            }
    if (c.StageName == 'Closed - Lost')
    {
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.Short_name__c = c.Short_name__c;
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Lost';
            Opp.Renewed_Opportunity_Link__c = c.Id;
            Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
            Opp.Lost_Cancel_Reason__c = null;
            Opp.Lost_Cancelled_Reason_Comment__c = null;
            Opp.Lost_Due_to_Pricing_Currency__c = null;
            Opp.Lost_Due_to_Pricing_amount__c = null;
            newOpps.add(Opp);
            c.Renewal_Opportunity_Link__c = opp.Id;
            }
       if(!InList.isEmpty()) { 
            update InList; 
        } 
        }
       insert newOpps;
       
        List<Messaging.SingleEmailMessage> sendEmailList = new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailMessage email;
        for(Opportunity opp : newOpps){
            email = new Messaging.SingleEmailMessage(); 
            string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
            email.setSubject('Renewal Opportunity - ' + opp.name); 
            email.setHTMLBody('A new renewal opportunity has been assigned to you : ' + opp.name + '     (link - '+  
                              URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id +' )' +
                              + '<br/>'  + 
                              '<br/>' + 'The previous opportunity was ' + Opp.Previously_won_or_lost__c 
                              + '     (link - '+  
                              URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.Renewed_Opportunity_Link__c +' )' +
                              + '<br/>' + ' and has an insured period to : ' + opp.Insured_period_from__c
                              + '<br/>' + '<br/>' + 'Details from the previous Opportunity : ' + '<br/>' + '<br/>' + Opp.Renewal_Information__c); 
            email.setToAddresses(toaddress);
            sendEmailList.add(email);
        }
        if(sendEmailList.size() > 0) {
            Messaging.sendEmail(sendEmailList);
        }

     }
           global void finish(Database.BatchableContext BC)
     {
    } 
}
Hi - I have finally built a scheduled apex class to create a renewal for my opportunities. The final part Im trying to configure is the email notifications. I can get everything working except the URL - i suspect this is because at the time of sending each email it hasnt committed the new opportunities so there is no ID yet addigned. Anyone know of a clever way to get round this ?

code so far is below. relevant lines highlighted in bold

global class CreateRenewal implements Schedulable { 
    global void execute(SchedulableContext ctx) { 

        List<Opportunity> InList = [Select 
        AccountID,
        Amount,
        CloseDate,
        CreatedByID,
        Description,
        ExpectedRevenue,
        ForecastCategoryName,
        LeadSource,
        NextStep,
        CurrencyIsoCode,
        Name,
        OwnerID,
        RecordTypeID,
        Pricebook2ID,
        CampaignID,
        IsPrivate,
        Probability,
        TotalOpportunityQuantity,
        IqScore,
        StageName,
        Type,
        Compliance__c,
        Coverholder_Commission__c,
        Local_Insurer_Commission__c,
        Local_Taxes__c,
        Reinsurance_broker_commission__c,
        Retail_broker_commission__c,
        Sum_Insured__c,
        Account_Contact__c,
        Additional_Amount_in_Oppty_Currency__c,
        Additional_Countries__c,
        Additional_tax_commission_cost_descripti__c,
        AXA_ASR_Pricing_Model_Version__c,
        Business_Type_Class__c,
        Cedents_retention__c,
        Cedents_Retention_Amount__c,
        Channel__c,
        Coinsurances_Commissions_from_Brokers__c,
        Coinsurances_Commissions_to_Brokers__c,
        Coinsurances_Commissions_to_Coverholder__c,
        Coinsurances_Percentage__c,
        Coinsurances_Premium__c,
        Contract_Type__c,
        Coverholder__c,
        Days_to_Quote_Released__c,
        DB_Competitor__c,
        Direct_Contact__c,
        Direct_Source__c,
        Estimated_S6130_GNP__c,
        Fast_track__c,
        Global_GNP__c,
        Insured_Period_From__c,
        Insured_Period_To__c,
        Intermediary_Commission__c,
        Intermediary_Account__c,
        Intermediary_Contact__c,
        Intermediary_Reinsurance_Broker__c,
        Intermediary_Reinsurance_Contact__c,
        Layer__c,
        LoB__c,
        Local_Insurer__c,
        Local_Insurer_Commission_Percentage__c,
        Local_Insurer_Contact__c,
        Lost_Cancel_Reason__c,
        Lost_Cancelled_Reason_Comment__c,
        Lost_Due_to_Pricing_amount__c,
        Lost_Due_to_Pricing_currency__c,
        Non_Renewable__c,
        Opportunity_Channel__c,
        P_Coverholder_Commission__c,
        P_Intermediary_Commission__c,
        P_Local_Insurer_Commission__c,
        P_Local_Taxes__c,
        Policy__c,
        Post_Underwriting_Compliance__c,
        Pre_Issue_Compliance__c,
        Pre_Underwriting_Compliance__c,
        Previously_won_or_lost__c,
        Pricing_Model_Source__c,
        Primary_Country__c,
        Proportional__c,
        P_Syndicate_Gross_Premium__c,
        P_Syndicate_Premium__c,
        Quote_Released_Date__c,
        Reinsurance_Facultative__c,
        Reinsurer_Taxes__c,
        Reinsurer_Taxes_Amount__c,
        Renewal_Created__c,
        Renewal_Indicator__c,
        Renewal_Information__c,
        Renewed_Opportunity__c,
        Rest_of_World__c,
        reviewScope__c,
        Risk_Category__c,
        AXA_GNP__c,
        S1084_S6130_Percentage__c,
        S6130_Coverholder_Commission__c,
        S6130_Coverholder_Commission_Amount__c,
        Syndicate_GGP__c,
        S6130_Line_Size__c,
        S6130_Local_Insurer_Commission__c,
        S6130_Local_Insurer_Commission_Amount__c,
        S6130_Local_Taxes__c,
        S6130_Local_Taxes_Amount__c,
        Syndicate_Percentage__c,
        S6130_Reinsurance_Broker_Commission__c,
        S6130_Reinsurance_Broker_Commission_Amou__c,
        S6130_Retail_Broker_Commission__c,
        S6130_Retail_Broker_Commission_Amount__c,
        Short_Name__c,
        Step__c,
        Subject_to_NDA__c,
        Sub_Status__c,
        Underwriter__c,
        UW_Reference__c,
        Renewal_Opportunity__c
        
        From Opportunity 
        where Opportunity.Insured_Period_to__c <= NEXT_90_DAYS 
        AND Opportunity.Renewal_Created__c != 'YES'
        AND (opportunity.StageName = 'Closed - Won' OR opportunity.StageName = 'Closed - Lost')]; 
        
        
        List<Opportunity> newOpps=new List<Opportunity>();

        for(Opportunity c: InList){
        
    if (c.StageName == 'Closed - Won'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Won';
            Opp.Renewed_Opportunity__c = opp.Name;
            Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
            newOpps.add(Opp);
                        {
                                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 
                                    string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
                                    email.setSubject('New Renewal Opportunity - ' + opp.name); 
                                    email.setHTMLBody('A new renewal opportnity has been assigned to you : ' +   
                                    URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id
                                    + '<br/>'  + 
                                    '<br/>' + 'The opportunity (' + c.name + ') was previously ' + Opp.Previously_won_or_lost__c +
                                    ' and has an insured period to : ' + c.Insured_period_to__c
                                    + '<br/>' + 'Details from the previous Opportunity : ' + Opp.Renewal_Information__c); 
                                    email.setToAddresses(toaddress); 
                                    Messaging.sendEmail(New Messaging.SingleEmailMessage[]{email}); 
                        } 
            }
    if (c.StageName == 'Closed - Lost'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Lost';
            Opp.Renewed_Opportunity__c = opp.Name;
            Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
            Opp.Lost_Cancel_Reason__c = null;
            Opp.Lost_Cancelled_Reason_Comment__c = null;
            Opp.Lost_Due_to_Pricing_Currency__c = null;
            Opp.Lost_Due_to_Pricing_amount__c = null;
            newOpps.add(Opp);
                        {
                                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 
                                    string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
                                    email.setSubject('Renewal Opportunity - ' + opp.name); 
                                    email.setHTMLBody('A new renewal opportnity has been assigned to you : ' +   
                                    URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id
                                    + '<br/>'  + 
                                    '<br/>' + 'The opportunity (' + c.name + ') was previously ' + Opp.Previously_won_or_lost__c +
                                    ' and has an insured period to : ' + c.Insured_period_to__c
                                    + '<br/>' + 'Details from the previous Opportunity : ' + Opp.Renewal_Information__c); 
                                    email.setToAddresses(toaddress); 
                                    Messaging.sendEmail(New Messaging.SingleEmailMessage[]{email}); 
                        } 
          }
       if(!InList.isEmpty()) { 
            update InList; 
        } 
        }
       insert newOpps;
     }
           global void finish(Database.BatchableContext BC)
     {
    } 
}
I have created an apex trigger to clone an opportunity but when executing it keeps adding multiple "_copy_copy_copy" unitil it blows the size limit. Im very new to this so apologies if its a basic question - what am i doing wrong ??

trigger Renewal on Opportunity (after update) {

if(Trigger.isUpdate){

List<Opportunity> listOppor = new List<Opportunity>();
for (Opportunity o: Trigger.new){

    if (o.StageName == 'Closed - Won' ){
        Opportunity oppNew = o.clone();
//        oppNew.Name = oppNew.Name + '_Renewal';
        oppNew.Renewal_Indicator__c = true;
        OppNew.CloseDate = OppNew.CloseDate.addyears(1);
        OppNew.Insured_period_from__c = OppNew.Insured_period_from__c.addyears(1);

        OppNew.Insured_period_to__c = OppNew.Insured_period_to__c.addyears(1);

        listOppor.add(oppNew);
    }// end if

    if(listOppor.size() > 0){
       insert listOppor;
     }//end if
}//end for
}//end if
}
Ive been looking at Apex Triggers to clone an opportunity as a "renewal opportunity" - to be created 3 months prior to the policy end date.

can this be done with an Apex Trigger ?

We have a custom object (Policy) which is created by a custom button available once the opportunity is Closed - Won. The Policy holds the name of the original opportunity. 3 months prior to policy completion im after a new opportunity cloned from the original with the year section of the name changed (first 4 digits).

Possible ?
Our opportunities have links to, potentially, several contacts (and accounts) as per:
User-added image

Whenever a contact is updated I want to check to see if it is linked to any opportunities.
Ive been trying to create an Apex trigger to update a field on the contact if the contact is linked to any opportunities as the account contact, intermediary reinsurance contact local insurer contact etc.

Ive tried building a trigger just focusing on the Account contact to start with:

trigger checkforopps on Contact (after update) {
    // Check if contact has related opportunities.
    for (Contact a : [SELECT Id FROM Contact
                     WHERE Id IN (SELECT Account_Contact__c FROM Opportunity) AND
                     Id IN :Trigger.old]) {
     a.GDPR_Contact_has_Opportunities__c = True;
    }

it never seems to set the tickbox on. Am i missing somethig daft ?
   }
I have an Apex class that runs based on a database enquiry and creates new opportunities (clones) where certain criteria are met. Im unsure how to build a test script for this ? Ive done all my testing in sandbox by running through the developer portal. For pushing to Production I now need a test script. I dont want loads of new opportunities created in production so Im not sure how I do this ? My Apex code is below. Any pointers appreciated 0 its my first Apex Class change.

global class CreateRenewal implements Schedulable { 
    global void execute(SchedulableContext ctx) { 

        List<Opportunity> InList = [Select 
        AccountID,
        Amount,
        CloseDate,
        CreatedByID,
        Description,
        ExpectedRevenue,
        ForecastCategoryName,
        LeadSource,
        NextStep,
        CurrencyIsoCode,
        Name,
        OwnerID,
        RecordTypeID,
        Pricebook2ID,
        CampaignID,
        IsPrivate,
        Probability,
        TotalOpportunityQuantity,
        IqScore,
        StageName,
        Type,
        Compliance__c,
        Coverholder_Commission__c,
        Local_Insurer_Commission__c,
        Local_Taxes__c,
        Reinsurance_broker_commission__c,
        Retail_broker_commission__c,
        Sum_Insured__c,
        Account_Contact__c,
        Additional_Amount_in_Oppty_Currency__c,
        Additional_Countries__c,
        Additional_tax_commission_cost_descripti__c,
        AXA_ASR_Pricing_Model_Version__c,
        Business_Type_Class__c,
        Cedents_retention__c,
        Cedents_Retention_Amount__c,
        Channel__c,
        Coinsurances_Commissions_from_Brokers__c,
        Coinsurances_Commissions_to_Brokers__c,
        Coinsurances_Commissions_to_Coverholder__c,
        Coinsurances_Percentage__c,
        Coinsurances_Premium__c,
        Contract_Type__c,
        Coverholder__c,
        Days_to_Quote_Released__c,
        DB_Competitor__c,
        Direct_Contact__c,
        Direct_Source__c,
        Estimated_S6130_GNP__c,
        Fast_track__c,
        Global_GNP__c,
        Insured_Period_From__c,
        Insured_Period_To__c,
        Intermediary_Commission__c,
        Intermediary_Account__c,
        Intermediary_Contact__c,
        Intermediary_Reinsurance_Broker__c,
        Intermediary_Reinsurance_Contact__c,
        Layer__c,
        LoB__c,
        Local_Insurer__c,
        Local_Insurer_Commission_Percentage__c,
        Local_Insurer_Contact__c,
        Lost_Cancel_Reason__c,
        Lost_Cancelled_Reason_Comment__c,
        Lost_Due_to_Pricing_amount__c,
        Lost_Due_to_Pricing_currency__c,
        Non_Renewable__c,
        Opportunity_Channel__c,
        P_Coverholder_Commission__c,
        P_Intermediary_Commission__c,
        P_Local_Insurer_Commission__c,
        P_Local_Taxes__c,
        Policy__c,
        Post_Underwriting_Compliance__c,
        Pre_Issue_Compliance__c,
        Pre_Underwriting_Compliance__c,
        Previously_won_or_lost__c,
        Pricing_Model_Source__c,
        Primary_Country__c,
        Proportional__c,
        P_Syndicate_Gross_Premium__c,
        P_Syndicate_Premium__c,
        Quote_Released_Date__c,
        Reinsurance_Facultative__c,
        Reinsurer_Taxes__c,
        Reinsurer_Taxes_Amount__c,
        Renewal_Created__c,
        Renewal_Indicator__c,
        Renewal_Information__c,
        Rest_of_World__c,
        reviewScope__c,
        Risk_Category__c,
        AXA_GNP__c,
        S1084_S6130_Percentage__c,
        S6130_Coverholder_Commission__c,
        S6130_Coverholder_Commission_Amount__c,
        Syndicate_GGP__c,
        S6130_Line_Size__c,
        S6130_Local_Insurer_Commission__c,
        S6130_Local_Insurer_Commission_Amount__c,
        S6130_Local_Taxes__c,
        S6130_Local_Taxes_Amount__c,
        Syndicate_Percentage__c,
        S6130_Reinsurance_Broker_Commission__c,
        S6130_Reinsurance_Broker_Commission_Amou__c,
        S6130_Retail_Broker_Commission__c,
        S6130_Retail_Broker_Commission_Amount__c,
        Short_Name__c,
        Step__c,
        Subject_to_NDA__c,
        Sub_Status__c,
        Underwriter__c,
        UW_Reference__c,
        Renewed_Opportunity_Link__c,
        Renewal_Opportunity_Link__c,
        Renewal_Opportunity__c
        
        From Opportunity 
        where Opportunity.Insured_Period_to__c <= NEXT_90_DAYS 
        AND Opportunity.LoB__c = 'Property'
        AND Opportunity.Insured_Period_to__c > :date.today()
        AND Opportunity.Renewal_Created__c != 'YES'
        AND (opportunity.StageName = 'Closed - Won' OR opportunity.StageName = 'Closed - Lost')]; 
        
        
        List<Opportunity> newOpps=new List<Opportunity>();

        for(Opportunity c: InList){
        
    if (c.StageName == 'Closed - Won'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.Short_name__c = c.Short_name__c;
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Won';
            Opp.Renewed_Opportunity_Link__c = c.Id;
            Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
            newOpps.add(Opp);
            c.Renewal_Opportunity_Link__c = opp.Id;
            }
    if (c.StageName == 'Closed - Lost')
    {
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.Short_name__c = c.Short_name__c;
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Lost';
            Opp.Renewed_Opportunity_Link__c = c.Id;
            Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
            Opp.Lost_Cancel_Reason__c = null;
            Opp.Lost_Cancelled_Reason_Comment__c = null;
            Opp.Lost_Due_to_Pricing_Currency__c = null;
            Opp.Lost_Due_to_Pricing_amount__c = null;
            newOpps.add(Opp);
            c.Renewal_Opportunity_Link__c = opp.Id;
            }
       if(!InList.isEmpty()) { 
            update InList; 
        } 
        }
       insert newOpps;
       
        List<Messaging.SingleEmailMessage> sendEmailList = new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailMessage email;
        for(Opportunity opp : newOpps){
            email = new Messaging.SingleEmailMessage(); 
            string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
            email.setSubject('Renewal Opportunity - ' + opp.name); 
            email.setHTMLBody('A new renewal opportunity has been assigned to you : ' + opp.name + '     (link - '+  
                              URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id +' )' +
                              + '<br/>'  + 
                              '<br/>' + 'The previous opportunity was ' + Opp.Previously_won_or_lost__c 
                              + '     (link - '+  
                              URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.Renewed_Opportunity_Link__c +' )' +
                              + '<br/>' + ' and has an insured period to : ' + opp.Insured_period_from__c
                              + '<br/>' + '<br/>' + 'Details from the previous Opportunity : ' + '<br/>' + '<br/>' + Opp.Renewal_Information__c); 
            email.setToAddresses(toaddress);
            sendEmailList.add(email);
        }
        if(sendEmailList.size() > 0) {
            Messaging.sendEmail(sendEmailList);
        }

     }
           global void finish(Database.BatchableContext BC)
     {
    } 
}
Hi - I have finally built a scheduled apex class to create a renewal for my opportunities. The final part Im trying to configure is the email notifications. I can get everything working except the URL - i suspect this is because at the time of sending each email it hasnt committed the new opportunities so there is no ID yet addigned. Anyone know of a clever way to get round this ?

code so far is below. relevant lines highlighted in bold

global class CreateRenewal implements Schedulable { 
    global void execute(SchedulableContext ctx) { 

        List<Opportunity> InList = [Select 
        AccountID,
        Amount,
        CloseDate,
        CreatedByID,
        Description,
        ExpectedRevenue,
        ForecastCategoryName,
        LeadSource,
        NextStep,
        CurrencyIsoCode,
        Name,
        OwnerID,
        RecordTypeID,
        Pricebook2ID,
        CampaignID,
        IsPrivate,
        Probability,
        TotalOpportunityQuantity,
        IqScore,
        StageName,
        Type,
        Compliance__c,
        Coverholder_Commission__c,
        Local_Insurer_Commission__c,
        Local_Taxes__c,
        Reinsurance_broker_commission__c,
        Retail_broker_commission__c,
        Sum_Insured__c,
        Account_Contact__c,
        Additional_Amount_in_Oppty_Currency__c,
        Additional_Countries__c,
        Additional_tax_commission_cost_descripti__c,
        AXA_ASR_Pricing_Model_Version__c,
        Business_Type_Class__c,
        Cedents_retention__c,
        Cedents_Retention_Amount__c,
        Channel__c,
        Coinsurances_Commissions_from_Brokers__c,
        Coinsurances_Commissions_to_Brokers__c,
        Coinsurances_Commissions_to_Coverholder__c,
        Coinsurances_Percentage__c,
        Coinsurances_Premium__c,
        Contract_Type__c,
        Coverholder__c,
        Days_to_Quote_Released__c,
        DB_Competitor__c,
        Direct_Contact__c,
        Direct_Source__c,
        Estimated_S6130_GNP__c,
        Fast_track__c,
        Global_GNP__c,
        Insured_Period_From__c,
        Insured_Period_To__c,
        Intermediary_Commission__c,
        Intermediary_Account__c,
        Intermediary_Contact__c,
        Intermediary_Reinsurance_Broker__c,
        Intermediary_Reinsurance_Contact__c,
        Layer__c,
        LoB__c,
        Local_Insurer__c,
        Local_Insurer_Commission_Percentage__c,
        Local_Insurer_Contact__c,
        Lost_Cancel_Reason__c,
        Lost_Cancelled_Reason_Comment__c,
        Lost_Due_to_Pricing_amount__c,
        Lost_Due_to_Pricing_currency__c,
        Non_Renewable__c,
        Opportunity_Channel__c,
        P_Coverholder_Commission__c,
        P_Intermediary_Commission__c,
        P_Local_Insurer_Commission__c,
        P_Local_Taxes__c,
        Policy__c,
        Post_Underwriting_Compliance__c,
        Pre_Issue_Compliance__c,
        Pre_Underwriting_Compliance__c,
        Previously_won_or_lost__c,
        Pricing_Model_Source__c,
        Primary_Country__c,
        Proportional__c,
        P_Syndicate_Gross_Premium__c,
        P_Syndicate_Premium__c,
        Quote_Released_Date__c,
        Reinsurance_Facultative__c,
        Reinsurer_Taxes__c,
        Reinsurer_Taxes_Amount__c,
        Renewal_Created__c,
        Renewal_Indicator__c,
        Renewal_Information__c,
        Renewed_Opportunity__c,
        Rest_of_World__c,
        reviewScope__c,
        Risk_Category__c,
        AXA_GNP__c,
        S1084_S6130_Percentage__c,
        S6130_Coverholder_Commission__c,
        S6130_Coverholder_Commission_Amount__c,
        Syndicate_GGP__c,
        S6130_Line_Size__c,
        S6130_Local_Insurer_Commission__c,
        S6130_Local_Insurer_Commission_Amount__c,
        S6130_Local_Taxes__c,
        S6130_Local_Taxes_Amount__c,
        Syndicate_Percentage__c,
        S6130_Reinsurance_Broker_Commission__c,
        S6130_Reinsurance_Broker_Commission_Amou__c,
        S6130_Retail_Broker_Commission__c,
        S6130_Retail_Broker_Commission_Amount__c,
        Short_Name__c,
        Step__c,
        Subject_to_NDA__c,
        Sub_Status__c,
        Underwriter__c,
        UW_Reference__c,
        Renewal_Opportunity__c
        
        From Opportunity 
        where Opportunity.Insured_Period_to__c <= NEXT_90_DAYS 
        AND Opportunity.Renewal_Created__c != 'YES'
        AND (opportunity.StageName = 'Closed - Won' OR opportunity.StageName = 'Closed - Lost')]; 
        
        
        List<Opportunity> newOpps=new List<Opportunity>();

        for(Opportunity c: InList){
        
    if (c.StageName == 'Closed - Won'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Won';
            Opp.Renewed_Opportunity__c = opp.Name;
            Opp.Renewal_Information__c = 'Original S6130 Line Size was : ' + Opp.S6130_Line_Size__c;
            newOpps.add(Opp);
                        {
                                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 
                                    string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
                                    email.setSubject('New Renewal Opportunity - ' + opp.name); 
                                    email.setHTMLBody('A new renewal opportnity has been assigned to you : ' +   
                                    URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id
                                    + '<br/>'  + 
                                    '<br/>' + 'The opportunity (' + c.name + ') was previously ' + Opp.Previously_won_or_lost__c +
                                    ' and has an insured period to : ' + c.Insured_period_to__c
                                    + '<br/>' + 'Details from the previous Opportunity : ' + Opp.Renewal_Information__c); 
                                    email.setToAddresses(toaddress); 
                                    Messaging.sendEmail(New Messaging.SingleEmailMessage[]{email}); 
                        } 
            }
    if (c.StageName == 'Closed - Lost'){
        Opportunity opp = c.clone();

            opp.StageName = 'New';
            opp.Renewal_Indicator__c = true;
            Opp.Insured_period_from__c = c.Insured_period_to__c;
            Opp.Insured_period_to__c = Opp.Insured_period_from__c.adddays(c.Insured_period_from__c.daysbetween(c.Insured_period_to__c));
            Opp.CloseDate = Opp.Insured_period_from__c.addmonths(-1);
            opp.Name = Opp.Insured_period_from__c.year() + '_' + c.Name.substringafter('_');
            c.Renewal_Opportunity__c = opp.name;    
            Opp.OwnerID = c.CreatedByID;
            c.Renewal_Created__c = 'Yes';
            Opp.Previously_won_or_lost__c = 'Lost';
            Opp.Renewed_Opportunity__c = opp.Name;
            Opp.Renewal_Information__c = 'Lost Reason : ' + c.Lost_Cancel_Reason__c + ' - comment : ' + c.Lost_Cancelled_Reason_Comment__c + ' - Pricing : ' + c.Lost_Due_to_Pricing_Currency__c + ' ' + c.Lost_Due_to_Pricing_amount__c;
            Opp.Lost_Cancel_Reason__c = null;
            Opp.Lost_Cancelled_Reason_Comment__c = null;
            Opp.Lost_Due_to_Pricing_Currency__c = null;
            Opp.Lost_Due_to_Pricing_amount__c = null;
            newOpps.add(Opp);
                        {
                                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); 
                                    string [] toaddress= New string[]{'stuart.harrison@axa.com'}; 
                                    email.setSubject('Renewal Opportunity - ' + opp.name); 
                                    email.setHTMLBody('A new renewal opportnity has been assigned to you : ' +   
                                    URL.getSalesforceBaseUrl().toExternalForm()+'/'+ opp.id
                                    + '<br/>'  + 
                                    '<br/>' + 'The opportunity (' + c.name + ') was previously ' + Opp.Previously_won_or_lost__c +
                                    ' and has an insured period to : ' + c.Insured_period_to__c
                                    + '<br/>' + 'Details from the previous Opportunity : ' + Opp.Renewal_Information__c); 
                                    email.setToAddresses(toaddress); 
                                    Messaging.sendEmail(New Messaging.SingleEmailMessage[]{email}); 
                        } 
          }
       if(!InList.isEmpty()) { 
            update InList; 
        } 
        }
       insert newOpps;
     }
           global void finish(Database.BatchableContext BC)
     {
    } 
}
I have created an apex trigger to clone an opportunity but when executing it keeps adding multiple "_copy_copy_copy" unitil it blows the size limit. Im very new to this so apologies if its a basic question - what am i doing wrong ??

trigger Renewal on Opportunity (after update) {

if(Trigger.isUpdate){

List<Opportunity> listOppor = new List<Opportunity>();
for (Opportunity o: Trigger.new){

    if (o.StageName == 'Closed - Won' ){
        Opportunity oppNew = o.clone();
//        oppNew.Name = oppNew.Name + '_Renewal';
        oppNew.Renewal_Indicator__c = true;
        OppNew.CloseDate = OppNew.CloseDate.addyears(1);
        OppNew.Insured_period_from__c = OppNew.Insured_period_from__c.addyears(1);

        OppNew.Insured_period_to__c = OppNew.Insured_period_to__c.addyears(1);

        listOppor.add(oppNew);
    }// end if

    if(listOppor.size() > 0){
       insert listOppor;
     }//end if
}//end for
}//end if
}
Ive been looking at Apex Triggers to clone an opportunity as a "renewal opportunity" - to be created 3 months prior to the policy end date.

can this be done with an Apex Trigger ?

We have a custom object (Policy) which is created by a custom button available once the opportunity is Closed - Won. The Policy holds the name of the original opportunity. 3 months prior to policy completion im after a new opportunity cloned from the original with the year section of the name changed (first 4 digits).

Possible ?
Our opportunities have links to, potentially, several contacts (and accounts) as per:
User-added image

Whenever a contact is updated I want to check to see if it is linked to any opportunities.
Ive been trying to create an Apex trigger to update a field on the contact if the contact is linked to any opportunities as the account contact, intermediary reinsurance contact local insurer contact etc.

Ive tried building a trigger just focusing on the Account contact to start with:

trigger checkforopps on Contact (after update) {
    // Check if contact has related opportunities.
    for (Contact a : [SELECT Id FROM Contact
                     WHERE Id IN (SELECT Account_Contact__c FROM Opportunity) AND
                     Id IN :Trigger.old]) {
     a.GDPR_Contact_has_Opportunities__c = True;
    }

it never seems to set the tickbox on. Am i missing somethig daft ?
   }