1

I'm new to Apex and trying to make quick work of a problem I thought would be easy to solve. Essentially, on a button click from an account page, I'd like an Apex Class called that compares our companies product catalog to the products already bought for that account, and returns a VisualForce page of products that are not yet bought. I haven't gotten around to writing the entire class at this point as I'm hung up on a specific problem right now.

Within the class I have a method which I'm using to query the account to identify products already bought and return the ProductCode field from the queried products to the Outer Class. From what I can see in debug logs it doesn't look like my method is executing, and I'm unsure why that is. Any help would be greatly appreciated.

public class AddOnTitlesGapAnalysis2 {

    list<Product2> products;
    public List<String> shortNamesOwned {get;set;}

    public static List<string> shortNames() {    
        List<String> shortNamesOwned = new List<String>() ;
        List<Product2> titleProductsOwned = [SELECT ID, ProductCode FROM Product2 p WHERE Child_Product_Line__c = 'Stand Alone Title'
                                         AND Id in (SELECT Product__c FROM Product_Invoice__c)];
        system.debug(titleProductsOwned);

        for (Product2 p2 :titleProductsOwned) {
            shortNamesOwned.add(p2.ProductCode);                            
        }

        return shortNamesOwned;
    }

    public List<Product2> getProducts() {
        system.debug(shortNamesOwned);
        if (products == null && shortNamesOwned != null) {
           products = [SELECT ID, Name, Publisher__c, Marketing_Imprint__c, ISBN__c, Primary_Universal_Subject__c, Phase__c, Essentials_Collection__c, Noteworthy_for_Marketing_Annotation__c, ProductCode, Short_Description__c
                       From Product2 WHERE Child_Product_Line__c = 'Stand Alone Title' AND IsActive = TRUE AND (Phase__c = 'Production' OR Phase__c = 'Live')
                       AND For_Sale_Options__c != 'Subscription Only' AND ProductCode not in: shortNamesOwned ORDER BY Name] ;
        }
        return products;             
    }  
}
  • How are you calling these methods? Have you created a test method to help you develop your code? If not, I recommend you use Test Driven Development to test your code to see that it meets your requirements as you continue to develop it. You'll then also have consistent and repeatable conditions in which to test/compare changes in your code. – crmprogdev Mar 4 '16 at 14:58
  • Thanks for the tip. I do have a test method and it returns the expected values. What I was struggling with was understanding specifically why it was not executing. The answer posted below cleared that up though. Thanks! – j.sweet Mar 4 '16 at 20:34
0

You need your button to navigate the user to a Visualforce page that extends the Account standard object class.

<apex:page standardcontroller="Account" extensions="AddOnTitlesGapAnalysis2" >

Your controller extension needs to access the Account like this:

public class AddOnTitlesGapAnalysis2 {

list<Product2> products{get;set;}
public List<String> shortNamesOwned {get;set;}
Public Account acc{get;set;]

Public AddOnTitlesGapAnalysis2(ApexPages.standardController c){
    this.acc = (Account)c.getRecord();
    this.shortNamesOwned = shortNames();
    this.products = getProducts();
}

public static List<string> shortNames() {    
    List<String> shortNamesOwned = new List<String>() ;
    List<Product2> titleProductsOwned = [SELECT ID, ProductCode FROM Product2 p WHERE Child_Product_Line__c = 'Stand Alone Title'
                                     AND Id in (SELECT Product__c FROM Product_Invoice__c)];
    system.debug(titleProductsOwned);

    for (Product2 p2 :titleProductsOwned) {
        shortNamesOwned.add(p2.ProductCode);                            
    }

    return shortNamesOwned;
}

public List<Product2> getProducts() {
    system.debug(shortNamesOwned);
    if (products == null && shortNamesOwned != null) {
       products = [SELECT ID, Name, Publisher__c, Marketing_Imprint__c, ISBN__c, Primary_Universal_Subject__c, Phase__c, Essentials_Collection__c, Noteworthy_for_Marketing_Annotation__c, ProductCode, Short_Description__c
                   From Product2 WHERE Child_Product_Line__c = 'Stand Alone Title' AND IsActive = TRUE AND (Phase__c = 'Production' OR Phase__c = 'Live')
                   AND For_Sale_Options__c != 'Subscription Only' AND ProductCode not in: shortNamesOwned ORDER BY Name] ;
    }
    return products;             
}  

}

You can do a quick check on your page to see what's being output by just displaying the controller properties to validate there's data being returned:

<apex:page standardcontroller="Account" extensions="AddOnTitlesGapAnalysis2" >
    Products: {!products}
    <br /><br />
    Names: {!shortNamesOwned}
</apex:page>

I think you want to use your Account Id somewhere in your Product_Invoice__c sub query to filter only to the Account you want to view, like " WHERE Account__c = :this.acc.Id"

  • Thanks for the comment Jason. You got ahead of me with your response but I appreciate you took the time to build the entire solution. Right now I have a VF page that is referencing my class directly without use of a standard controller and it works without error. Do I have to utilize the Account standard controller in order to pull in the Account ID? – j.sweet Mar 4 '16 at 19:08
  • if your page is based on one specific account you're trying to access, then it's best practice to simply extend the standard Account object class. It also allows you to use a "Visualforce Page Button" on your Account page layout. You don't have to use it, per se, in that you can make a javascript button and manually pass the Id in a parameter - like "/apex/myPage?aId={!Account.Id}", however a VF button type will do that for you automatically. If you choose to pass the Id as a param via JS button, then in your controller you'd do: id acctId = ApexPages.currentPage().getPrameters().get("aId") – Jason Benkert Mar 5 '16 at 1:21
  • Thanks for the clarification. The last question I have relates to your last sentence and how to reference the Account Id when querying for ownership of existing products in the class method. When I try and reference the Acc ID as this.acc.Id, I get a variable does not exist error. Do I have to reference specifically the public account that is returned into the outer class for a class method, or is there some other way to grab the Account Id? Thanks – j.sweet Mar 6 '16 at 22:30
  • just before you do the query, declare a local Id inside your method like this: Id thisAcctId = this.acc.Id; then, in your soql query, use :thisAcctId instead. – Jason Benkert Mar 7 '16 at 3:24

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.