• Chris Leszka 5
  • NEWBIE
  • 0 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 3
    Questions
  • 3
    Replies
Hello, In our org we have different divisions each with their own sales reps that all sell to the same accounts.  Once a sale has been made, the Account Management team steps in and takes over and is in charge of maintaining renewals for the account.  Because products are broken out between different opportunities, the team has struggled to find an efficient way to let a customer know which of their subscriptions are coming up for renewal, without having to manually piece together the details from multiple opportunities manually.

To solve for this, I created a custom object call Renewal_Package__c.  This is a simple object that allows the team to link all related opportunities for an account to a package and then ideally, be able to generate an email with the details of all those opportunities broken out within it.  Renewal_Package__c has a Master-Detail relationship with Account, and a couple other custom fields where the user can enter in a date and a note about the package.  Because you can't have a Master-Detail relationship with the Opportunities object, i have a lookup field on Opportunities where you can lookup the Renewal Package and link it appropriately.  This lookup, then populates to the product level as well via a workflow rule.  With this setup, you can look at a Renewal Package record and see the related list for Opportunities as well as all the individual products from the opportunities.

Now the hard part - I'm trying to setup a Visualforce email template that pulls in a related list of all of those Opportunity Products.  Here is my code:
<messaging:emailTemplate subject="Your Upcoming Renewal" recipientType="User" relatedToType="Renewal_Package__c">
<messaging:htmlEmailBody >
<html>
<body>

 <br>Your subscriptions are expiring soon!  Please review the list of products below and let us know whether you'll be continuing your subscription with us, so that we can ensure you have no disruptions in access to the data you rely on.   </br>

 <h3>Expiring Renewable Products</h3>                  
        <table border="3" cellpadding="10" width="100%" >
            <tr > 
               <th>Product Name</th><th>Quantity</th><th>Unit Price</th><th>Start Date</th><th>End Date</th><th>Additional Details</th><th>Renewal Approved</th>
           </tr>
        <apex:repeat var="opp" value="{!relatedTo.Renewal_Package__r.Opportunitylineitems}">
           <tr>
               <td align="center">{!opp.PriceBookEntry.name}</td>
               <td align="center">{!ROUND(opp.Quantity,0)}</td>
               <td align="center">
                   <apex:outputText value="{0,number,$###,###,##0.00}">
                       <apex:param value="{!ROUND(opp.UnitPrice,0)}" />
                   </apex:outputText></td>                                                                
               <td align="center">
                   <apex:outputText value="{0,date, M/dd/yyyy}">
                       <apex:param value="{!opp.ServiceDate}" />
                   </apex:outputText></td>
               <td align="center">
                   <apex:outputText value="{0,date, M/dd/yyyy}">
                       <apex:param value="{!opp.Service_End_Date__c}" />
                   </apex:outputText></td>                   
               <td align="center">{!opp.Description}</td>  
               <td align="center"></td>                            
           </tr>
         </apex:repeat>
         </table>        
<p/>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

The error I receive is "Error: Invalid field Renewal_Package__r for SObject Renewal_Package__c", so it's failing at the first lookup in the related list table: <apex:repeat var="opp" value="{!relatedTo.Renewal_Package__r.Opportunitylineitems}">.

Is it possible to reference the opportunity and/or Opportunity products with how i have everything setup?  I've tried a few variations of the code, but it errors every time.

Any help would be appreciated.
Thank you in advance!
I'm looking for a way to add a static text message above the standard edit/create new opportunity page layout.  The business case for this is to provide instructions/tips for opportunity creation, right where the opportunity is being created.  I'm able to add my text to the standard layouts, but just can't get it to appear on the edit/create page.  Here is as far as i've been able to get - and this just gets me the standard create page with none of my text anywhere on the screen.
 
<apex:page standardController="Opportunity" action="{!create}"> 
<apex:pageblock title="Help"> Fill in all the known details of this opportunity, including contacts, billing information and when you think the deal will close by.<br/> 
***If you are creating a new opportunity, your initial stage CANNOT be Closed - Pending, Closed - Submitted or Closed - Booked. You must start from a lower stage and then shift to a closed Stage after initial creation.<p/> 
<apex:detail inlineEdit="True" relatedList="true"/> 
</apex:pageBlock> 
<apex:detail />
​</apex:page>

 
I created a trigger in my sandbox that creates an Asset for all renewable products in closedwon opportunity.  I'm not a developer in any way, so my process for building the trigger was to search the web for some code that was close to what I needed, and modify it to match my needs.  That said, the trigger works perfectly in the sandbox, but when i try to move it to production, it won't let me deploy it because it fails the test classes.  I don't have any test classes built specific to this trigger, and don't really know how to/where to even begin, so i'm hoping someone here can help me.

Here is my trigger code:
trigger CreateAssetonClosedWon on Opportunity (after update) {
map<id,map<id,asset>> assets = new map<id,map<id,asset>>();
  set<id> prodids = new set<id>();
  opportunitylineitem[] lines = [select id, totalprice, servicedate, service_end_date__c, quantity, pricebookentry.product2id, pricebookentry.product2.name, description, opportunityid from opportunitylineitem where opportunityid in :trigger.new and product2.business_group__c = 'TECH' and opportunity.StageName = 'Closed - Booked' and converted_to_asset__c = false];
  for(opportunitylineitem line:lines)
    prodids.add(line.pricebookentry.product2id);
  for(opportunity record:trigger.new)
    assets.put(record.accountid,new map<id,asset>());
  for(asset record:[select id, accountid, product2id, quantity, price, purchasedate, status, installdate, UsageEndDate, description, name from asset where accountid in :assets.keyset() and product2id in :prodids]) {
    assets.get(record.accountid).put(record.product2id,record);
    if(record.quantity==null)
      record.quantity=0;
    if(record.price==null)
      record.price=0;
  }
  for(opportunitylineitem line:lines) {
    opportunity lineopp = trigger.newmap.get(line.opportunityid);
    asset ast = assets.get(lineopp.accountid).get(line.pricebookentry.product2id);
    if(ast==null)
      ast = new asset(quantity=0,price=0);
    ast.accountid = lineopp.accountid;
    ast.product2id = line.pricebookentry.product2id;
    ast.quantity += line.quantity;
    ast.price += line.TotalPrice;
    ast.purchasedate = lineopp.closedate;
    ast.status = 'Purchased';
    ast.description = line.description;
    ast.installdate = line.servicedate;
    ast.usageenddate = line.service_end_date__c;
    ast.source_opportunity__c = lineopp.id;
    ast.name = line.pricebookentry.product2.name;
    assets.get(lineopp.accountid).put(line.pricebookentry.product2id,ast);
  }
  asset[] updates = new asset[0];
  for(id accountid:assets.keyset())
    updates.addall(assets.get(accountid).values());
  upsert updates;
  for(opportunitylineitem line:lines)
    line.converted_to_asset__c = true;
  update lines;
}

 
I'm looking for a way to add a static text message above the standard edit/create new opportunity page layout.  The business case for this is to provide instructions/tips for opportunity creation, right where the opportunity is being created.  I'm able to add my text to the standard layouts, but just can't get it to appear on the edit/create page.  Here is as far as i've been able to get - and this just gets me the standard create page with none of my text anywhere on the screen.
 
<apex:page standardController="Opportunity" action="{!create}"> 
<apex:pageblock title="Help"> Fill in all the known details of this opportunity, including contacts, billing information and when you think the deal will close by.<br/> 
***If you are creating a new opportunity, your initial stage CANNOT be Closed - Pending, Closed - Submitted or Closed - Booked. You must start from a lower stage and then shift to a closed Stage after initial creation.<p/> 
<apex:detail inlineEdit="True" relatedList="true"/> 
</apex:pageBlock> 
<apex:detail />
​</apex:page>

 
Hello, In our org we have different divisions each with their own sales reps that all sell to the same accounts.  Once a sale has been made, the Account Management team steps in and takes over and is in charge of maintaining renewals for the account.  Because products are broken out between different opportunities, the team has struggled to find an efficient way to let a customer know which of their subscriptions are coming up for renewal, without having to manually piece together the details from multiple opportunities manually.

To solve for this, I created a custom object call Renewal_Package__c.  This is a simple object that allows the team to link all related opportunities for an account to a package and then ideally, be able to generate an email with the details of all those opportunities broken out within it.  Renewal_Package__c has a Master-Detail relationship with Account, and a couple other custom fields where the user can enter in a date and a note about the package.  Because you can't have a Master-Detail relationship with the Opportunities object, i have a lookup field on Opportunities where you can lookup the Renewal Package and link it appropriately.  This lookup, then populates to the product level as well via a workflow rule.  With this setup, you can look at a Renewal Package record and see the related list for Opportunities as well as all the individual products from the opportunities.

Now the hard part - I'm trying to setup a Visualforce email template that pulls in a related list of all of those Opportunity Products.  Here is my code:
<messaging:emailTemplate subject="Your Upcoming Renewal" recipientType="User" relatedToType="Renewal_Package__c">
<messaging:htmlEmailBody >
<html>
<body>

 <br>Your subscriptions are expiring soon!  Please review the list of products below and let us know whether you'll be continuing your subscription with us, so that we can ensure you have no disruptions in access to the data you rely on.   </br>

 <h3>Expiring Renewable Products</h3>                  
        <table border="3" cellpadding="10" width="100%" >
            <tr > 
               <th>Product Name</th><th>Quantity</th><th>Unit Price</th><th>Start Date</th><th>End Date</th><th>Additional Details</th><th>Renewal Approved</th>
           </tr>
        <apex:repeat var="opp" value="{!relatedTo.Renewal_Package__r.Opportunitylineitems}">
           <tr>
               <td align="center">{!opp.PriceBookEntry.name}</td>
               <td align="center">{!ROUND(opp.Quantity,0)}</td>
               <td align="center">
                   <apex:outputText value="{0,number,$###,###,##0.00}">
                       <apex:param value="{!ROUND(opp.UnitPrice,0)}" />
                   </apex:outputText></td>                                                                
               <td align="center">
                   <apex:outputText value="{0,date, M/dd/yyyy}">
                       <apex:param value="{!opp.ServiceDate}" />
                   </apex:outputText></td>
               <td align="center">
                   <apex:outputText value="{0,date, M/dd/yyyy}">
                       <apex:param value="{!opp.Service_End_Date__c}" />
                   </apex:outputText></td>                   
               <td align="center">{!opp.Description}</td>  
               <td align="center"></td>                            
           </tr>
         </apex:repeat>
         </table>        
<p/>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

The error I receive is "Error: Invalid field Renewal_Package__r for SObject Renewal_Package__c", so it's failing at the first lookup in the related list table: <apex:repeat var="opp" value="{!relatedTo.Renewal_Package__r.Opportunitylineitems}">.

Is it possible to reference the opportunity and/or Opportunity products with how i have everything setup?  I've tried a few variations of the code, but it errors every time.

Any help would be appreciated.
Thank you in advance!
I created a trigger in my sandbox that creates an Asset for all renewable products in closedwon opportunity.  I'm not a developer in any way, so my process for building the trigger was to search the web for some code that was close to what I needed, and modify it to match my needs.  That said, the trigger works perfectly in the sandbox, but when i try to move it to production, it won't let me deploy it because it fails the test classes.  I don't have any test classes built specific to this trigger, and don't really know how to/where to even begin, so i'm hoping someone here can help me.

Here is my trigger code:
trigger CreateAssetonClosedWon on Opportunity (after update) {
map<id,map<id,asset>> assets = new map<id,map<id,asset>>();
  set<id> prodids = new set<id>();
  opportunitylineitem[] lines = [select id, totalprice, servicedate, service_end_date__c, quantity, pricebookentry.product2id, pricebookentry.product2.name, description, opportunityid from opportunitylineitem where opportunityid in :trigger.new and product2.business_group__c = 'TECH' and opportunity.StageName = 'Closed - Booked' and converted_to_asset__c = false];
  for(opportunitylineitem line:lines)
    prodids.add(line.pricebookentry.product2id);
  for(opportunity record:trigger.new)
    assets.put(record.accountid,new map<id,asset>());
  for(asset record:[select id, accountid, product2id, quantity, price, purchasedate, status, installdate, UsageEndDate, description, name from asset where accountid in :assets.keyset() and product2id in :prodids]) {
    assets.get(record.accountid).put(record.product2id,record);
    if(record.quantity==null)
      record.quantity=0;
    if(record.price==null)
      record.price=0;
  }
  for(opportunitylineitem line:lines) {
    opportunity lineopp = trigger.newmap.get(line.opportunityid);
    asset ast = assets.get(lineopp.accountid).get(line.pricebookentry.product2id);
    if(ast==null)
      ast = new asset(quantity=0,price=0);
    ast.accountid = lineopp.accountid;
    ast.product2id = line.pricebookentry.product2id;
    ast.quantity += line.quantity;
    ast.price += line.TotalPrice;
    ast.purchasedate = lineopp.closedate;
    ast.status = 'Purchased';
    ast.description = line.description;
    ast.installdate = line.servicedate;
    ast.usageenddate = line.service_end_date__c;
    ast.source_opportunity__c = lineopp.id;
    ast.name = line.pricebookentry.product2.name;
    assets.get(lineopp.accountid).put(line.pricebookentry.product2id,ast);
  }
  asset[] updates = new asset[0];
  for(id accountid:assets.keyset())
    updates.addall(assets.get(accountid).values());
  upsert updates;
  for(opportunitylineitem line:lines)
    line.converted_to_asset__c = true;
  update lines;
}

 
I'm simply looking for a custom link that will do a search on LinkedIn from the Account and Contact tabs.
Account Tab would do a "company" search within LinkedIn.
Contact Tab would do a contact search within LinkedIn
  • August 19, 2008
  • Like
  • 0