function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jan DrommershausenJan Drommershausen 

Need little help with grouped line item list.

Hello everybody, maybe someone can help me? I stuck again with my Extension Controller / maybe with my visualforce Page too. 

I am training myself in a Developer-Edition, to understand Controllers and Visiualforce more.

 

I builded a Visualforce Page which is the Template for the Salesforce Quote Template (rendered as PDF)

My Quote line Items are sorted by a line Item Field maually by the user. All this worked out well.

 

Now i wanted push this more forward. My Goal is to sort the line items in groups so i can give out a price for every group.

 

For Example:

Group 1         Group Total Value 60 €             

#1   Line item a   10€

#2   Line item b   20€

#3   Line item c   30€

 

Group 2         Group Total Value 180 €

#4   Line item d   50€

#5   Line item e   60€

#6   Line item f    70€

 

.... and so on

 

What i did:

There is a custom Object called "QuotePhase" where Quote is the Master Object.

I have a Lookup field on the QuoteLineItems so i can reference them to the different Phases/Groups

- also set up a lookup-filter to make sure a user can only select a Phase that belongs to the quote which is the master of the Phase

- and a apex trigger which calculates values of all related Items related to the Phase (rollup is not available for lookups :-/ )

 

So here i stuck: i don't get the list to work proberbly.

I think its maybe a little detail on my controller or my List call on the visualforce. But all my try and error approaches brought me to results here.

 

Here is my Controller Extension:

public with sharing class ExtensionControllerQuote {

    public List<QuoteLineItem> QuoteLineItemsSorted {public get; private set;}
    public List<QuotePhase__c> QuotePhaseSorted {public get; private set;}
    Quote selectedQuote = new Quote();
    
    // constructor
    public ExtensionControllerQuote(ApexPages.StandardController cont)
    {
        selectedQuote = (Quote)cont.getRecord();
        QuoteLineItemsSorted = new List<QuoteLineItem>();
        QuoteLineItemsSorted =
            [Select o.New_Section_Headline__c,
                    o.Sort_Order__c,
                    o.Quantity,
                    o.Einheit__c,
                    o.PricebookEntry.Name,
                    o.PricebookEntryId,
                    o.Product_lineitem_description__c,
                    o.UnitPrice,
                    o.TotalPrice
             From QuoteLineItem o
             Where o.QuoteId =: selectedQuote.id
             ORDER BY Sort_Order__c ASC
             limit 1000
                ];
        selectedQuote = (Quote)cont.getRecord();
        QuotePhaseSorted = new List<QuotePhase__c>();
        QuotePhaseSorted =
            [Select q.Sum_of_Phases__c,
                    q.Name
             From QuotePhase__c q
             Where q.RelatedQuoteID__c =: selectedQuote.id
             ORDER BY q.Name ASC
             limit 1000
                ];

    }
}


And here Code Snippets out of my Visualforce:

<apex:page standardController="Quote" renderas="pdf" showHeader="false" extensions="ExtensionControllerQuote">

 

.... Blah blah ..... there comes the repeat:

 

<apex:repeat value="{!QuotePhaseSorted}" var="phase">
{QuotePhase_Name}
    <apex:repeat value="{!QuoteLineItemsSorted}" var="line">
       {!line.Quantity}
    </apex:repeat>
</apex:repeat>

 

</apex:page>

 

If needed i can post the whole Visualforce code here. But i guess i made an obvious error somewhere which is maybe easy to find for those who are more skilled than me. Please teach me what i do wrong here.

 

bob_buzzardbob_buzzard

So at the moment are you seeing all quote line items inside each each group (aka quote phase)?

 

Looking at the code, that's what I'd expect, as there doesn't appear to be anything retrieved with the quote line item that links it to a phase.

 

If you want to display items grouped in this way, I'd suggest you look at using a wrapper class that contains the quote phase and its associated line items.

 

I think something like the following should work (not compiled, but should get you started):

 

Controller:

 

 

// at top of class
public List<QuotePhaseWrapper> quotePhases {get; set;}


   // at the end of the ExtensionControllerQuote constructor
   // assuming that the lookup to the quote phase is in the line item
   // field 'Quote_Phase__c

   quotePhases=new List<QuotePhaseWrapper>();
   for (QuotePhase__c phase : QuotePhaseSorted)
   {
      QuotePhaseWrapper qwp=new QuotePhaseWrapper();
      qwp.quotePhase=phase;
      for (QuoteLineItem qli : QuoteLineItemsSorted)
      {
         if (qli.Quote_Phase__c==phase.id)
         {
            qwp.quoteLineItems.add(qli);
         }
      }
      quotePhases.add(qwp);
  }
}  // end of constructor

public class QuotePhaseWrapper
{
   public QuotePhase__c quotePhase {get; set;}
   public List<QuoteLineItem> quoteLineItems {get; set;}

   public QuotePhaseWrapper()
   {
      quoteLineItems=new List<QuoteLineItem>();
   }
}

 

 

Page:

 

 

<apex:repeat value="{!quotePhases}" var="phase">
{!phase.quotePhase.Name}
    <apex:repeat value="{!phase.QuoteLineItems}" var="line">
       {!line.Quantity}
    </apex:repeat>
</apex:repeat>
 

 

 

 (Edited to reflect bug picked up by Alexander_E)

 

Jan DrommershausenJan Drommershausen

Thanks again Bob, i will test and play around with your code (which i can only do in my free time, so might take a couple of days), if i get it to work i will post it here.

If not, i guess i post this as well :smileyhappy: Whish me luck.

Alexander_EAlexander_E

Hello,

 

for all people, who trying this code, please use this fields in the VFPage

 

<apex:repeat value="{!quotePhases}" var="phase">
{!phase.quotePhase.Name}
    <apex:repeat value="{!phase.QuoteLineItems}" var="line">
       {!line.Quantity}
    </apex:repeat>
</apex:repeat>

 

there is a little mistake from Bobs code.

instead of calling the variable with phase.phase.Name

you should use phase.quotePhase.Name

 

:-)

bob_buzzardbob_buzzard

Good catch Alexander_E.  I've edited the original post to correct this (and credited you with the catch!).

Alexander_EAlexander_E

 

Hi Bob,

 

I have problems to cover one part of the extensionclass for testing.

 

This part in the extensioncontroller is marked red:

	   for (QuotePhase__c phase : QuotePhaseSorted)
	   {
	      QuotePhaseWrapper qwp=new QuotePhaseWrapper();
	      qwp.quotePhase = phase;
	      for (QuoteLineItem qli : QuoteLineItemsSorted)
	      {
	         if (qli.QuotePhase__c == phase.id)
	         {
	            qwp.quoteLineItems.add(qli);
	         }
	      }
	      quotePhases.add(qwp);
	  }

 

This is my version of a testclass for the ExtensionControllerQuote class: But that covers only 66% :-(

 

@isTest
private class TestExtensionControllerQuote {

	public static testMethod void testExtensionControllerQuote() {
        // TO DO: implement unit test
        Account testaccount = new Account (Name = 'TestAccount');
        insert testaccount;
        Date onedate = Date.valueOf('2009-04-04');
        Product2 testprod = new Product2(Name='TestProduct',Description='TestDescription');
        
        Opportunity testopportunity = new Opportunity (Name = 'TestOpp', 
        							StageName = 'Prospecting', 
        							CloseDate = onedate, 
        							AccountId = testaccount.Id);
        insert testopportunity;
        
        Quote testquote = new Quote ( Name = 'TestQuote', 
        					OpportunityId = testopportunity.Id );
        insert testquote;
        
        QuotePhase__c testphase = new QuotePhase__c ( 
        										QuotePhaseName_Formula__c = 'Phase 00: 123456890', 
        										Quote__c = testquote.Id );
        insert testphase;
        
        QuoteLineItem testlineitem = new QuoteLineItem(
        							QuotePhase__c = testphase.Id, 
        							QuoteId = testquote.Id);
        
		QuotePhaseWrapper qwp=new QuotePhaseWrapper();
		qwp.quoteLineItems.add(testlineitem);
		qwp.quotePhase =testphase;

		//get user
    	User tstuser = [select id from user where isActive=true LIMIT 1];
    	
    	// generate page
    	PageReference pageRef = Page.Test_Page;
    	Test.setCurrentPage(pageRef);
        ApexPages.currentPage().getParameters().put('Id', testquote.id); 
    	
    	ApexPages.Standardcontroller controller = New ApexPages.StandardController(testquote);
        ExtensionControllerQuote ext = new ExtensionControllerQuote(controller); 
		
		List<QuotePhaseWrapper> testextquotePhases = new List<QuotePhaseWrapper>();
    	List<QuoteLineItem> testextQuoteLineItemsSorted = new List<QuoteLineItem>();
    	List<QuotePhase__c> testextQuotePhaseSorted = new List<QuotePhase__c>();
		
		System.currentPageReference().getParameters().put('testquoteId', testquote.id);
		
		ext.QuotePhaseSorted.add(testphase);
		ext.QuoteLineItemsSorted.add(testlineitem);
		ext.quotePhases.add(qwp);
		
	    qwp.quotePhase = testphase;
        qwp.quoteLineItems.add(testlineitem);
		system.debug(ApexPages.currentPage().getUrl());
		try {
		
		system.assertEquals(qwp.quotePhase, ext.QuotePhaseSorted[0]);
		system.assertEquals(qwp.quoteLineItems[0], ext.QuoteLineItemsSorted[0]);
		system.assertEquals(qwp, ext.quotePhases[0]);
		}
		catch (ListException e) {
			system.debug('Test failed!');
		}
    }    
}

 

Can you help us?

bob_buzzardbob_buzzard

Before you construct the controller you need to insert the quotelineitem. That way there will be elements in the database for the constructor to extract and wrap.