1

So I have a custom object Campaign__c which I need to relate with the Opportunity object. This will be many-to-many, so I've created a junction object called Campaign_plan__c with lookup (also tried M-D) to the other two objects (schema below). SChema

The workflow will be:

  • User creates a new "Campaign" record
  • User will need to add existing Opportunities to this Campaign
  • User should also have the option to create new Opportunities from here, and associate them with the Campaign

What I have so far:

  • I've added the Campaign_Plan__c related list to the Campaign__c object, with two custom buttons
  • First button "Add Opportunity" takes you to a create new Campaign_Plan__c (junction) record with the Opportunity lookup field, to pick the Opportunity to add
  • Second button "Create Opportunities" is a VF page that lets the user create a bunch of Opportunities and save them

Issue(s):

  • While the "Create Opportunities" works fine, I'm struggling to pass on the "Campaign" ID or create a Campaign_Plan__c (junction) object record

I tried a trigger, but I'm only able to create a junction object record while creating the Opportunity record and associate with that.

trigger CreateCampPlan on Opportunity (after insert) { List camplan = new List();

for (Opportunity newOpp: Trigger.New) 
    {
        camplan.add(new Campaign_Plan__c(
                    Deal__c = newOpp.Id));
    }
insert camplan;
}

Apex Class and VF to create bulk opportunities

    <apex:page controller="ManageListController" tabstyle="Opportunity">
 <apex:form >
   <apex:pageBlock title="Create associated Deals">
      <apex:pageBlockTable value="{!wrappers}" var="wrapper" id="wtable">
         <apex:column headerValue="Ident">
            <apex:outputText value="{!wrapper.ident}"/>
         </apex:column>
         <apex:column headerValue="Deal Name">
            <apex:inputField value="{!wrapper.opp.Name}"/>
         </apex:column>
         <apex:column headerValue="Account">
            <apex:inputField value="{!wrapper.opp.AccountId}"/>
         </apex:column>
         <apex:column headerValue="Expected Local NOI">
            <apex:inputField value="{!wrapper.opp.Amount}"/>
         </apex:column>
          <apex:column headerValue="Expected Sale Start Date">
            <apex:inputField value="{!wrapper.opp.CloseDate}"/>
         </apex:column>
          <apex:column headerValue="Deal Status">
            <apex:inputField value="{!wrapper.opp.StageName}"/>
         </apex:column>
         <apex:column headerValue="Action">
            <apex:commandButton value="Delete" action="{!delWrapper}" rerender="wtable">
               <apex:param name="toDelIdent" value="{!wrapper.ident}" assignTo="{!toDelIdent}"/> 
            </apex:commandButton>
         </apex:column>
      </apex:pageBlockTable>
      <apex:commandButton value="Add Row" action="{!addRows}" rerender="wtable">
         <apex:param name="addCount" value="1" assignTo="{!addCount}"/> 
      </apex:commandButton>
      <apex:commandButton value="Add 5 Rows" action="{!addRows}" rerender="wtable">
         <apex:param name="addCount" value="5" assignTo="{!addCount}"/> 
      </apex:commandButton>
      <apex:commandButton value="Save" action="{!save}"/>
   </apex:pageBlock>
 </apex:form>
</apex:page>


public class ManageListController 
{
 public List<OpportunityWrapper> wrappers {get; set;}
 public static Integer toDelIdent {get; set;}
 public static Integer addCount {get; set;}
 private Integer nextIdent=0;

 public ManageListController()
 {
  wrappers=new List<OpportunityWrapper>();
  for (Integer idx=0; idx<5; idx++)
  {
   wrappers.add(new OpportunityWrapper(nextIdent++));
  }
 }

 public void delWrapper()
 {
  Integer toDelPos=-1;
  for (Integer idx=0; idx<wrappers.size(); idx++)
  {
   if (wrappers[idx].ident==toDelIdent)
   {
    toDelPos=idx;
   }
  }

  if (-1!=toDelPos)
  {
   wrappers.remove(toDelPos);
  }
 }

 public void addRows()
 {
  for (Integer idx=0; idx<addCount; idx++)
  {
   wrappers.add(new OpportunityWrapper(nextIdent++));
  }
 }

 public PageReference save()
 {
  List<Opportunity> opps=new List<Opportunity>();
  for (OpportunityWrapper wrap : wrappers)
  {
   opps.add(wrap.opp);
  }

  insert opps;

  return new PageReference('/' + Schema.getGlobalDescribe().get('Opportunity').getDescribe().getKeyPrefix() + '/o');
 }

 public class OpportunityWrapper
 {
  public Opportunity opp {get; private set;}
  public Integer ident {get; private set;}

  public OpportunityWrapper(Integer inIdent)
  {
   ident=inIdent;
   opp=new Opportunity(Name='');
  }
 }
}

Any ideas? Let me know if you need more info. As always, thanks so much for your help!

  • Can you clarify what isn't working? You say the "Create Opportunities" works fine, but isn't that where the problem is? Is it that it creates the Opportunities, but doesn't create the junction object record? – Nick Cook Feb 17 '15 at 9:45
  • Nick, that trigger by itself works fine. It creates a junction object record and associates it with the Opportunity. But I'm stuck at figuring out how to associate the junction record with the Campaign record. – Quicksilvr Feb 17 '15 at 9:58
1

I'd probably make the VF page use the Campaign__c standard controller, that way you can access the Campaign__c record within the extension and therefore associate the new Campaign_Plan__c records with the original Campaign record.

i.e.

<apex:page standardController="Campaign__c" extensions="ManageListController" />

Then in your constructor use:

public class ManageListController 
{
    ....
    private final Campaign__c campy;
    ....
    public ManageListController(ApexPages.StandardController stdController)
    {
        this.campy = (Campaign__c)stdController.getRecord();
        ....
    }
}

By doing this, you have the Campaign__c record and can therefore get the Id.

You could then loop through the Opportunities you've created and add in the Campaign__c records.

public PageReference save()
{
    ....
    insert opps;

    List<Campaign_plan__c> cpToInsert = new List<Campaign_plan__c>();
    for(Opportunity oppy : opps)
    {
        cpToInsert.add(new Campaign_plan__c(Deal__c = oppy.Id, Campaign__c = campy.Id));
    }

    insert cpToInsert;
}

NOTE: This sort of works, although I don't think it works the way you want it to. The button needs to be on the detail of the Campaign__c record rather than the related list.

  • Thanks Nick. For some reason, it does not seem to affect my VF page. I changed my controller on the VF page as suggested, also added the class to the controller. I still can't seem to get the Campaign Id. – Quicksilvr Feb 17 '15 at 17:08
  • Are you receiving any error messages or exceptions? It might be worth adding in a bunch of system.debug statements to determine where it's not working. i.e. is it correctly identifying the Campaign__c record? does it create the Campaign_plan__c records and does the insert work? I'm assuming you've disabled the trigger as it's not working. – Nick Cook Feb 18 '15 at 13:18
  • Something else came up so I haven't spent enough time with it yet. But the logic should work, so I'll mark it as answered. I'll test it out over the weekend and report back. Thanks so much Nick! – Quicksilvr Feb 19 '15 at 16:36
  • I quickly tested this and I noticed a mistake with the for loop which I have now fixed. It works, but I think it's probably not quite at the level you're after. i.e. you have to enter at least 5 opportunities. – Nick Cook Feb 20 '15 at 12:02
  • Nick, I tested it out this morning, it does work. I haven't tried it with a button yet, but just the URL with a Campaign record ID creates the junction obj record as desired. Thanks again for your help. Appreciate it!! – Quicksilvr Feb 21 '15 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.