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 help with sorting tables for Opp Items

First of all, Hello Developer Community 

 

I am new here, and to be honest, i need help. I am working with salesforce since almost two years and i am now getting more interested into visualforce. I know this is Apex Code Development, but i think you are the ones how may can help me (If the admins think i am wrong here, feel free to move this topic).

 

So here my Problem:

 

I tested the new Quotes Module, but i am not satisfied with the editor for the PDF Layout. I take a look and found this:

http://appexchange.salesforce.com/listingDetail?listingId=a0N300000017lEqEAI

I don't have Problems with customizing the Page layout, but i noticed that all Opp Line items are not inserted in the Visualforce page like they are sorted in the Opportunity (seems to be sorted by Product Name, alphabetically).

 

What i read so far is that i need a custom controller or maybe just an extension to control the sort order. I created a Custom field for Quote Product Position (Sort_order) which should be the master for sorting the line items.

 

After i tested and played around with all the Code-Examples i found in the web, nothing worked out for me. Now, after almost a week i decided to ask you for a hint, or an example which is almost (or exactly :D ) what i need. I forgot to mention i have almost no programming skills :(

 

Maybe there is also a way to use the sort order of the opportunity itself, that would be the best way, but what i read so far, this is not possible.

 

Here is my Visualforce Page, so you can see my apex:repeat element with all the fields:

 

<apex:page standardController="Opportunity" showHeader="false" renderas="pdf">

<table border="0" cellspacing="0" cellpadding="0" width="100%" id="table1">
<tr>
    <td>
        <img src='{!URLFOR($Resource.YOUR_SL_Logo_quote)}' title="logo" />
    </td>
    <td  align="right"><font face="Arial" >
    <b>Quote  for {!Opportunity.Account.Name}</b></font><br/>
    </td>
    
    
</tr>

<hr/>

</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%" id="table1">
<tr>    <td><font face="Arial" >
        {!$Organization.Name}<br/>
        {!$Organization.Street}<br/>
        {!$Organization.PostalCode} {!$Organization.City}<br/>
        {!$Organization.Country}<br/>
        </font></td> 
        <td width="60%">&nbsp;</td>
   <td ><font face="Arial">Quote number: {!Opportunity.QuoteNumber__c}
   {!Opportunity.QuoteVersion__c}<br/>
        <br/>
        Offer valid Through:&nbsp;<apex:OutputField value="{!Opportunity.CloseDate}"/><br/>    
        Proposed by: {!Opportunity.Owner.LastName} {!Opportunity.Owner.FirstName}</font>
     </td>
</tr>
</table>
<br/>
<hr/>
<p><b><font face="Arial" color="#000080">Address Information</font></b></p>

<table border="0" width="100%" id="table2">
<tr>
       <td colspan="3">
           <font face="Arial">Account name: {!Opportunity.Account.Name} <br/><br/></font>
       </td>
</tr>
<tr>
       <td>          
           <font face="Arial">Bill To:<br/>
                             {!Opportunity.Account.BillingStreet}<br/>
                             {!Opportunity.Account.BillingPostalCode} {!Opportunity.Account.BillingCity}
           </font>
      </td>
        <td width="50%"></td>
        <td >
           <font face="Arial">Ship To:<br/>
                              {!Opportunity.Account.ShippingStreet}<br/>
                              {!Opportunity.Account.ShippingPostalCode} {!Opportunity.Account.ShippingCity}
           </font>
        </td>
</tr>    
</table>
<br/>
<hr/>
<p><b><font color="#000080" face="Arial">Products</font></b></p>
<p>&nbsp;</p>
<table border="0" width="100%" id="table4">
<tr>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Pos.</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Anz.</strong></font></td>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Einheit</strong></font></td>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Beschreibung</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Einzelpreis</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Gesamtpreis</strong></font></td>
</tr>

<tr>
       
       <apex:repeat value="{!Opportunity.OpportunityLineItems}" var="line">
          <tr>
             <td ALIGN="left" VALIGN="top"><strong>{!line.New_Section_on_quote__c}</strong></td>
          </tr> 
          <tr>
             <td ALIGN="left" VALIGN="top"> <p><strong>{!line.Sort_Order__c}</strong></p></td>
             <td ALIGN="right" VALIGN="top"><p>{!line.Quantity}</p></td>
             <td ALIGN="left" VALIGN="top"> <p>{!line.Einheit__c}</p></td>             
             <td ALIGN="left" VALIGN="top"> <p><strong>{!line.PricebookEntry.Name}</strong></p>
                                            <p>{!line.Product_lineitem_description__c}</p></td>
             <td ALIGN="right" VALIGN="top"><p><apex:OutputField value="{!line.UnitPrice}"/></p></td>
             <td ALIGN="right" VALIGN="top"><p><apex:OutputField value="{!line.TotalPrice}"/></p></td>
          </tr>
       </apex:repeat>  
</tr>

<tr>
       <td align="right" colspan="6">
       <font face="Arial"><b>Summe:</b>&nbsp;<apex:OutputField value="{!Opportunity.Amount}"/></font></td>
</tr>
</table>
<br/>
<hr/>
<p><b><font color="#000080" face="Arial">Terms and Conditions</font></b></p>
<table border="0" width="100%" id="table3">
<tr>
        <td><font face="Arial">
        
              Start date:&nbsp;<apex:OutputField value="{!Opportunity.QuoteBeginDate__c}"/><br/>
              Contract End date:&nbsp;<apex:OutputField value="{!Opportunity.QuoteEndDate__c}"/><br/>
            </font>
        </td>
        <td width="50%"></td>
        <td><font face="Arial">
              Payment Method:<apex:OutputField value="{!Opportunity.QuotePaymentMode__c}"/><br/>
              Payment Terms: <apex:OutputField value="{!Opportunity.QuotePaymentTime__c}"/><br/>
              Billing Frequency: <apex:OutputField value="{!Opportunity.QuoteBillingFrequency__c}"/><br/>
            </font>
       </td>
</tr>
</table>
<br/>
<p><font face="Arial">{!Opportunity.Conditions__c}</font></p>
<br/>
<hr/>
<table width="100%" id="table5">
<tr>
   <td width="50%"><b>{!$Organization.Name}</b></td>
   <td width="50%"><b>{!Opportunity.Account.Name}</b></td>
</tr>
<tr>
   <td width="50%">&nbsp;</td>
   <td width="50%">&nbsp;</td>
</tr>
<tr>
   <td width="50%">Signature<hr color="black" size="1"/></td>
   <td width="50%">Signature<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Name<hr color="black" size="1"/></td>
   <td width="50%">Name<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Title<hr color="black" size="1"/></td>
   <td width="50%">Title<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Date<hr color="black" size="1"/></td>
   <td width="50%">Date<hr color="black" size="1"/></td>
</tr>
</table>
<p>&nbsp;</p>
<hr/>
<p align="center"><font face="Arial"><i>Copyright {!$Organization.Name}.</i></font></p>
</apex:page>

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
petergascoynepetergascoyne
public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItem> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ExtensionControllerName(ApexPages.StandardController cont)
	{
		selectedOpp = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItem>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
} 

All Answers

petergascoynepetergascoyne

Hey,

 

I had quick look at your issue and have writen an extension controller you need which sorts the Opp line items by Sort_Order__c.

 

I did this quick and have not run the code so it may have some issue. Just let me know of any problems.

 

Here is the extension controller for your page to sort Opp Line Items by Sort_Order__c

public with sharing class ExtensionControllerName {
	
	List<OpportunityLineItems> OppLineItemsSorted = new List<OpportunityLineItems> {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ControllerName(ApexPages.StandardController cont)
	{
		selectedOpp.acct = (Opportunity)cont.getRecord();
		OppLineItemsSorted = 
			[Select New_Section_on_quote__c,
				Sort_Order__c, Quantity, Einheit__c, PricebookEntry, 
				Product_lineitem_description__c, UnitPrice, TotalPrice
			 From OpportunityLineItem
			 Where OpportunityId = selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
}

Here is your updated page using the extenstion controller

<apex:page standardController="Opportunity" showHeader="false" renderas="pdf" extensions="ExtenstionControllerName">

<table border="0" cellspacing="0" cellpadding="0" width="100%" id="table1">
<tr>
    <td>
        <img src='{!URLFOR($Resource.YOUR_SL_Logo_quote)}' title="logo" />
    </td>
    <td  align="right"><font face="Arial" >
    <b>Quote  for {!Opportunity.Account.Name}</b></font><br/>
    </td>
    
    
</tr>

<hr/>

</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%" id="table1">
<tr>    <td><font face="Arial" >
        {!$Organization.Name}<br/>
        {!$Organization.Street}<br/>
        {!$Organization.PostalCode} {!$Organization.City}<br/>
        {!$Organization.Country}<br/>
        </font></td> 
        <td width="60%">&nbsp;</td>
   <td ><font face="Arial">Quote number: {!Opportunity.QuoteNumber__c}
   {!Opportunity.QuoteVersion__c}<br/>
        <br/>
        Offer valid Through:&nbsp;<apex:OutputField value="{!Opportunity.CloseDate}"/><br/>    
        Proposed by: {!Opportunity.Owner.LastName} {!Opportunity.Owner.FirstName}</font>
     </td>
</tr>
</table>
<br/>
<hr/>
<p><b><font face="Arial" color="#000080">Address Information</font></b></p>

<table border="0" width="100%" id="table2">
<tr>
       <td colspan="3">
           <font face="Arial">Account name: {!Opportunity.Account.Name} <br/><br/></font>
       </td>
</tr>
<tr>
       <td>          
           <font face="Arial">Bill To:<br/>
                             {!Opportunity.Account.BillingStreet}<br/>
                             {!Opportunity.Account.BillingPostalCode} {!Opportunity.Account.BillingCity}
           </font>
      </td>
        <td width="50%"></td>
        <td >
           <font face="Arial">Ship To:<br/>
                              {!Opportunity.Account.ShippingStreet}<br/>
                              {!Opportunity.Account.ShippingPostalCode} {!Opportunity.Account.ShippingCity}
           </font>
        </td>
</tr>    
</table>
<br/>
<hr/>
<p><b><font color="#000080" face="Arial">Products</font></b></p>
<p>&nbsp;</p>
<table border="0" width="100%" id="table4">
<tr>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Pos.</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Anz.</strong></font></td>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Einheit</strong></font></td>
       <td ALIGN="left" VALIGN="top"><font face="Arial"><strong>Beschreibung</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Einzelpreis</strong></font></td>
       <td ALIGN="right" VALIGN="top"><font face="Arial"><strong>Gesamtpreis</strong></font></td>
</tr>

<tr>
       
       <apex:repeat value="{!OppLineItemsSorted}" var="line">
          <tr>
             <td ALIGN="left" VALIGN="top"><strong>{!line.New_Section_on_quote__c}</strong></td>
          </tr> 
          <tr>
             <td ALIGN="left" VALIGN="top"> <p><strong>{!line.Sort_Order__c}</strong></p></td>
             <td ALIGN="right" VALIGN="top"><p>{!line.Quantity}</p></td>
             <td ALIGN="left" VALIGN="top"> <p>{!line.Einheit__c}</p></td>             
             <td ALIGN="left" VALIGN="top"> <p><strong>{!line.PricebookEntry.Name}</strong></p>
                                            <p>{!line.Product_lineitem_description__c}</p></td>
             <td ALIGN="right" VALIGN="top"><p><apex:OutputField value="{!line.UnitPrice}"/></p></td>
             <td ALIGN="right" VALIGN="top"><p><apex:OutputField value="{!line.TotalPrice}"/></p></td>
          </tr>
       </apex:repeat>  
</tr>

<tr>
       <td align="right" colspan="6">
       <font face="Arial"><b>Summe:</b>&nbsp;<apex:OutputField value="{!Opportunity.Amount}"/></font></td>
</tr>
</table>
<br/>
<hr/>
<p><b><font color="#000080" face="Arial">Terms and Conditions</font></b></p>
<table border="0" width="100%" id="table3">
<tr>
        <td><font face="Arial">
        
              Start date:&nbsp;<apex:OutputField value="{!Opportunity.QuoteBeginDate__c}"/><br/>
              Contract End date:&nbsp;<apex:OutputField value="{!Opportunity.QuoteEndDate__c}"/><br/>
            </font>
        </td>
        <td width="50%"></td>
        <td><font face="Arial">
              Payment Method:<apex:OutputField value="{!Opportunity.QuotePaymentMode__c}"/><br/>
              Payment Terms: <apex:OutputField value="{!Opportunity.QuotePaymentTime__c}"/><br/>
              Billing Frequency: <apex:OutputField value="{!Opportunity.QuoteBillingFrequency__c}"/><br/>
            </font>
       </td>
</tr>
</table>
<br/>
<p><font face="Arial">{!Opportunity.Conditions__c}</font></p>
<br/>
<hr/>
<table width="100%" id="table5">
<tr>
   <td width="50%"><b>{!$Organization.Name}</b></td>
   <td width="50%"><b>{!Opportunity.Account.Name}</b></td>
</tr>
<tr>
   <td width="50%">&nbsp;</td>
   <td width="50%">&nbsp;</td>
</tr>
<tr>
   <td width="50%">Signature<hr color="black" size="1"/></td>
   <td width="50%">Signature<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Name<hr color="black" size="1"/></td>
   <td width="50%">Name<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Title<hr color="black" size="1"/></td>
   <td width="50%">Title<hr color="black" size="1"/></td>
</tr>
<tr>
   <td width="50%">Date<hr color="black" size="1"/></td>
   <td width="50%">Date<hr color="black" size="1"/></td>
</tr>
</table>
<p>&nbsp;</p>
<hr/>
<p align="center"><font face="Arial"><i>Copyright {!$Organization.Name}.</i></font></p>
</apex:page>

Hope this might help. : )

Jan DrommershausenJan Drommershausen

Hi gazza8,

 

thank you, but for the Controller i recive :

Compile Error: expecting right curly bracket, found 'public' at line 3 column 84

 

petergascoynepetergascoyne

Try this:

 

public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItems> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ControllerName(ApexPages.StandardController cont)
	{
		selectedOpp.acct = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItems>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
}

 

 

 

petergascoynepetergascoyne

Spotted one more error:

 

public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItems> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ControllerName(ApexPages.StandardController cont)
	{
		selectedOpp = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItems>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
}

 

 

Jan DrommershausenJan Drommershausen

Seems to work, but now comes the next error:

 

Invalid constructor name: ControllerName at line 7 column 12

 

: (

petergascoynepetergascoyne

Last one I hope:

 

public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItems> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ExtensionControllerName(ApexPages.StandardController cont)
	{
		selectedOpp.acct = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItems>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
}

 

 

Jan DrommershausenJan Drommershausen

nope sorry. with this i am getting:

Compile Error: Invalid type: OpportunityLineItems at line 3 column 17

petergascoynepetergascoyne

 

public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItem> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ExtensionControllerName(ApexPages.StandardController cont)
	{
		selectedOpp.acct = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItems>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
} 

 

Jan DrommershausenJan Drommershausen

Compile Error: Invalid type: OpportunityLineItems at line 10 column 39

petergascoynepetergascoyne
public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItem> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ExtensionControllerName(ApexPages.StandardController cont)
	{
		selectedOpp.acct = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItem>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
} 
Jan DrommershausenJan Drommershausen

Still not working out  : /

 

Invalid field acct for SObject Opportunity at line 9 column 9

petergascoynepetergascoyne
public with sharing class ExtensionControllerName {
	
	public List<OpportunityLineItem> OppLineItemsSorted {public get; private set;}
	Opportunity selectedOpp = new Opportunity();
	
	// constructor
	public ExtensionControllerName(ApexPages.StandardController cont)
	{
		selectedOpp = (Opportunity)cont.getRecord();
		OppLineItemsSorted = new List<OpportunityLineItem>();
		OppLineItemsSorted = 
			[Select o.New_Section_on_quote__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 OpportunityLineItem o
			 Where o.OpportunityId =: selectedOpp.id
			 ORDER BY Sort_Order__c ASC
			 limit 1000
				];
	}
	
} 
This was selected as the best answer
Jan DrommershausenJan Drommershausen

The last Controller have no Errors left! Thank you very very much.

there was a Typo in the Page at this point:

 

<apex:page standardController="Opportunity" showHeader="false" renderas="pdf" extensions="ExtensionControllerName">

 

Everything works out fine, the table is now sorted by the Sort order field.

 

Two thumbs up!

sfdcfoxsfdcfox

Use OpportunityLineItems when making a sub-query ( "select id,(select id from opportunitylineitems) from opportunity" ), but use only the singular name, not the plural name, when making a list of them ( "List<OpportunityLineItem>" or "OpportunityLineItem[]").

tasedataseda

Any chance you could help with the testing class on this?  Having a huge struggle.

 

Thanks!

Jan DrommershausenJan Drommershausen

Hi, actually i switched over to Sort Line Items on a visiualforce page on the Quote module, but i got some help from a collegue who knows a little more about apex than me. So he is the one who wrote the test class for this. 

 

I am posting the code here, even if i don't understand it : ) My collegue deleted all information he thought would be critical.

Maybe it gives you an idea how to write your Test Class. 

 

@isTest
private class TestExtensionControllerQuote {

	public static testMethod void testExtensionControllerQuote() {
		
        // testaccount
        Account testaccount = new Account (Name = 'TestAccount');
        insert testaccount;
        
        // onedate
        Date onedate = Date.valueOf('2009-04-04');
        
        // testprod
        Product2 testprod = new Product2(Name='TestProduct',Description='TestDescription');
        insert testprod;
        
        // testopportunity
        Opportunity testopportunity = new Opportunity (Name = 'TestOpp', 
        							StageName = 'Prospecting', 
        							CloseDate = onedate, 
        							AccountId = testaccount.Id);
        insert testopportunity;
        
		// pb = standart Pricebook
		Pricebook2 pb =[select name,isactive from Pricebook2 where isStandard=true];
		if(!pb.isactive){
		pb.isactive=true;
		Database.update(pb);
		}
		
		// testquote
		Quote testquote = new Quote ( Name = 'TestQuote', 
        					OpportunityId = testopportunity.Id,
        					Pricebook2Id=pb.id );
        insert testquote;
        

        
		// stage = OpportunityStage for Masterlabel
		OpportunityStage stage=[select Masterlabel from OpportunityStage where Masterlabel != '' limit 1];
		
		// opp = Opportunity
		Opportunity opp = new Opportunity();
		opp.Name='TestOpp';
		opp.AccountID=testaccount.id;
		opp.CloseDate=date.today();
		opp.StageName=stage.masterlabel;
		opp.Pricebook2Id=pb.id;
		insert opp;
		
		// p = Product
		Product2 p = new Product2();
		p.Name='TestProd';
		p.IsActive=true;
		insert p;
		
		// sumTotalPrice = double
		double sumTotalPrice = 2.0;
		
		// SumOfPhase = double
		double SumOfPhase = 0.0;
		
		//pbe = pricebook entry
		PricebookEntry pbe=new PricebookEntry();
		pbe.Pricebook2Id=pb.id;
		pbe.Product2Id=p.id;
		pbe.UnitPrice = sumTotalPrice;
		pbe.IsActive=true;
		insert pbe;
		
		
		// testlineitem = QuoteLineItem
		// test2lineitem = QuoteLineItem
		QuoteLineItem testlineitem = new QuoteLineItem();
		QuoteLineItem test2lineitem = new QuoteLineItem();
		testlineitem.QuoteId=testquote.id;
		testlineitem.PricebookEntryId=pbe.id;
		testlineitem.quantity=1;
		testlineitem.discount=0.0;  
		//testlineitem.totalprice = sumTotalPrice;
		testlineitem.UnitPrice = sumTotalPrice;
		insert testlineitem;

        // qwp = QuotePhaseWrapper
		QuotePhaseWrapper qwp=new QuotePhaseWrapper();
		qwp.quoteLineItems.add(testlineitem);
		qwp.quotePhase =testphase;

		//user
		Profile admin = [select id, name from Profile where name = 'System Administrator' OR name = 'Systemadministrator']; 
    	List<User> testusers = [select email, id, name, ProfileId from user where isActive=true and ProfileId= :admin.Id LIMIT 1];
    	system.assert ( testusers.size() == 1);

    	for (Integer i = 0; i < 1;i++){
    		System.runAs(testusers[i]) {
    			system.debug('username' + testusers[i].name);
    		}}
    	
    	// generate page
    	PageReference pageRef = Page.Quote2PDF_Page;
    	pageRef.getParameters().put('id', testquote.id); 
    	Test.setCurrentPage(pageRef);
    	
    	//System.Debug('#testquote:' + testquote); positiv
    	
    			System.Debug('#QuoteLineItems: ' + [Select 
                    o.Quantity, 
                    o.PricebookEntry.Name, 
                    o.PricebookEntryId, 
                    o.UnitPrice, 
                    o.TotalPrice
                   From QuoteLineItem o 
                   Where o.QuoteId =: ApexPages.currentpage().getParameters().get('id')
                   ORDER BY Sort_Order__c ASC limit 100
            ]);
    	
    	ApexPages.Standardcontroller controller = New ApexPages.StandardController(testquote);
    	
    	//System.Debug('#controller: ' + controller); == 'ApexPages.StandardController[Quote]'
        ExtensionControllerQuote ext = new ExtensionControllerQuote(controller); 
        ext.init();
        
        String nextPage = controller.save().getUrl();
        string testquoteid = '/' + testquote.Id;
        //nextPage = '/' + nextPage;
        
        // Verify that page fails without parameters  
        System.assertEquals( testquoteid.substring(0,16),  nextPage.substring(0,16));
//		system.debug('testquoteid.substring(0,18) ' + testquoteid.substring(0,12));
//		system.debug('nextPage' + nextPage);
		List<QuotePhaseWrapper> testextquotePhases = new List<QuotePhaseWrapper>();
    	List<QuoteLineItem> testextQuoteLineItemsSorted = new List<QuoteLineItem>();
		
		//System.currentPageReference().getParameters().put('testquote.Id', testquote.id);
	
		ext.QuotePhaseSorted.add(testphase);
		ext.QuoteLineItemsSorted.add(testlineitem);
		ext.quotePhases.add(qwp);
		
		system.assertequals(ext.QuotePhaseSorted[0].Id,testphase.Id);
		system.assertequals(ext.QuoteLineItemsSorted[0].Id,testlineitem.Id);
		//system.assertequals(ext.quotePhases[0],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 Alex!');
		}
		
		
		List<QuotePhaseWrapper> quotePhases  = new List<QuotePhaseWrapper> () ;
 		List<QuoteLineItem> QuoteLineItemsSorted = new List<QuoteLineItem>() ;
		Quote selectedQuote = new Quote();
		

 			
 			   QuoteLineItemsSorted = new List<QuoteLineItem>();
  	   			QuoteLineItemsSorted =
						  	   [ Select Id From QuoteLineItem Where QuoteId =: testquote.Id
						  	   ORDER BY Sort_Order__c ASC limit 100
  	   			];
  	   			
  	   List<QuotePhaseWrapper> quotePhases2  = new List<QuotePhaseWrapper> () ;

  	   for (QuotePhase__c phase : QuotePhaseSorted)
  	   {
	  	   QuotePhaseWrapper qwp2=new QuotePhaseWrapper();
	  	   qwp2.quotePhase = testphase;
	  	   for (QuoteLineItem qli : [ Select Id,
	  	  							 QuoteId, PricebookEntryId, quantity, discount, totalprice, Sort_Order__c, QuotePhase__c, UnitPrice
	  	    						From QuoteLineItem Where QuoteId =: testquote.Id])
	  	   {
		  	   system.assert(qli.QuotePhase__c == QuotePhaseSorted[0].Id);
			  	   qwp2.quoteLineItems.add(qli);
	  	   }
 	 	   quotePhases2.add(qwp2);
  	   }
  	   
  	   //system.assert( ext.QuotePhaseSorted == QuotePhaseSorted);
  	   	system.debug('ext.QuotePhaseSorted' + ext.QuotePhaseSorted.size() );
  	   	system.debug('quotePhases2' + quotePhases2 );
  	   	//system.assertequals(quotePhases2[0].quotePhase.Id,testphase.Id);
		//system.assertequals(quotePhases2[0].quoteLineItems[0].Id,testlineitem.Id);
		//system.assertequals(quotePhases[1],qwp);

    } // end testmethod
    
    
        static testMethod void TestQuotePhaseSumChangeTrigger() {
        // 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');

        insert testprod;
        
        Opportunity testopportunity = new Opportunity (Name = 'TestOpp', 
        							StageName = 'Prospecting', 
        							CloseDate = onedate, 
        							AccountId = testaccount.Id);
        insert testopportunity;
        
		// Get the standard pricebook
		Pricebook2 pb =[select name,isactive from Pricebook2 where isStandard=true];
		if(!pb.isactive){
		pb.isactive=true;
		Database.update(pb);
		}
		
		Quote testquote = new Quote ( Name = 'TestQuote', 
        					OpportunityId = testopportunity.Id,
        					Pricebook2Id=pb.id );
        insert testquote;
        
        QuotePhase__c testphase = new QuotePhase__c ( 
        										QuotePhaseName_Formula__c = 'Phase 00: 123456890', 
        										Quote__c = testquote.Id );
        insert testphase;
		// get valid stage name
		OpportunityStage stage=[select Masterlabel from OpportunityStage where Masterlabel != '' limit 1];
		
		// setup basic opportunity
		Opportunity opp = new Opportunity();
		opp.Name='TestOpp';
		opp.AccountID=testaccount.id;
		opp.CloseDate=date.today();
		opp.StageName=stage.masterlabel;
		opp.Pricebook2Id=pb.id;
		insert opp;
		
		// Create a product2
		Product2 p = new Product2();
		p.Name='TestProd';
		p.Produktname_lang__c ='TestDescription';
		p.IsActive=true;
		insert p;
		

		double sumTotalPrice = 2.0;
		//Create pricebook entry
		PricebookEntry pbe=new PricebookEntry();
		pbe.Pricebook2Id=pb.id;
		pbe.Product2Id=p.id;
		pbe.UnitPrice = sumTotalPrice;
		pbe.IsActive=true;
		insert pbe;
		double SumOfPhase = 0.0;
		
		system.assertEquals(testphase.Sum_of_Phases__c, null);
		
		// create opportunity line item
		QuoteLineItem testlineitem = new QuoteLineItem();
		QuoteLineItem test2lineitem = new QuoteLineItem();
		testlineitem.QuoteId=testquote.id;
		testlineitem.PricebookEntryId=pbe.id;
		testlineitem.quantity=1;
		testlineitem.discount=0.0;  
		//testlineitem.totalprice = sumTotalPrice;
		testlineitem.Sort_Order__c = 1;
		testlineitem.QuotePhase__c = testphase.Id;
		testlineitem.UnitPrice = sumTotalPrice;
		insert testlineitem;
		system.assertNotEquals(testphase.Sum_of_Phases__c, SumOfPhase);
		system.assertEquals(testlineitem.TotalPrice, testphase.Sum_of_Phases__c);
		test2lineitem = [select Id, TotalPrice, UnitPrice, quantity from QuoteLineItem where Id =: testlineitem.Id];
		system.assertEquals(testlineitem.UnitPrice, sumTotalPrice);

		// create opportunity line item
		testlineitem.quantity=2;
		update testlineitem;
		system.assertEquals(testlineitem.TotalPrice, testphase.Sum_of_Phases__c);
		test2lineitem = [select Id, TotalPrice, UnitPrice, quantity from QuoteLineItem where Id =: testlineitem.Id];
		system.assertEquals(testlineitem.quantity, test2lineitem.quantity);
		system.assertEquals(testlineitem.UnitPrice, test2lineitem.UnitPrice);
		system.assertEquals(testlineitem.quantity, test2lineitem.quantity);
		system.assertEquals(testlineitem.TotalPrice, testphase.Sum_of_Phases__c);
		delete testlineitem;
		system.assertEquals(null, testphase.Sum_of_Phases__c);
		try {
			    update testlineitem;
			} catch (system.Dmlexception e) {
			    system.assert( e.getMessage().contains('entity is deleted'));
			}

    }
    
    
    
} // end class

 

Good Luck!

    
tasedataseda

Thanks!

 

Quick question, was what you switched to a simpler solution?  If so, could you post that one (with testing class).  I'm actually trying out orderedLineItems, but again, it's the testing class that is throwing me for a loop!

 

Thanks again!