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
Sammy7Sammy7 

Need help with test class for quote

I am new to test classes, but Im pulling my hair on this one. 

Below is my trigger to create an invoice from Quote once opp is closed and quotetoinvoice checkbox is ticked: 

trigger CreateInvoice on Opportunity (after update, after insert) {
    List<Invoice__c> invoiceList = new List<Invoice__c>();
    List<InvoiceLineItem__c> invoiceLineItemList = new List<InvoiceLineItem__c>();
    Set<Id> oppIdSet = new Set<Id>();
    
    // We only care about opportunities that are closed won
    for(Opportunity o : trigger.new)
    {
        if (o.stagename=='Closed Won')
        {
            oppIdSet.add(o.id);
        }
    }

    // Need to grab all the quotes and their subsequent quotelineitems under all the opportunities that fired the trigger, but select quotes that has QuotetoInvoice=True
    List<Quote> quoteList = [SELECT id, quotenumber, Accountid, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingName, Shippingname, ShippingStreet, ShippingCity, ShippingPostalCode, ShippingState, REP__c, Totalprice, Opportunityid, name, QuotetoInvoice__c, 
                (SELECT id, ListPrice, PricebookEntry.name, PricebookEntry.ProductCode, TotalPrice, Quantity FROM quotelineitems) 
                FROM Quote WHERE Opportunityid in: oppIdSet AND QuotetoInvoice__c=TRUE]; 
    
    // Create an invoice for each quote
    for (Quote q : quoteList)
    {
        Invoice__c newInvoice = new Invoice__c();
        newInvoice.Invoice_number__c=q.quotenumber;
        newInvoice.opportunity__c= q.Opportunityid;
        newInvoice.Bill_To__c=q.Billingname;
        newInvoice.BillingStreet__c=q.Billingstreet;
        newInvoice.BillingCity__c= q.BillingCity;
        newInvoice.BillingState__c= q.BillingState;
        newInvoice.BillingZip__c= q.BillingPostalCode;
        newInvoice.Ship_To__c=q.Shippingname;
        newInvoice.ShippingStreet__c=q.Shippingstreet;
        newInvoice.ShippingCity__c= q.ShippingCity;
        newInvoice.ShippingState__c= q.ShippingState;
        newInvoice.ShippingZip__c= q.ShippingPostalCode;
        newInvoice.Total__c=q.Totalprice;
        newInvoice.Customer__c=q.Accountid;
        newInvoice.REP__c=q.REP__c;
        invoiceList.add(newInvoice);
    }
    
    // We need to insert the invoices first, before being able to insert the invoicelineitems under it.
    insert invoiceList;
    // Construct this set as a copy of the invoiceList so we can remove from it easily later
    Set<Invoice__c> invoiceSet = new Set<Invoice__c>(invoiceList);
    
    // Create the invoicelineitems
    for (Quote q : quoteList)
    {
        for (QuoteLineItem qli : q.quotelineitems)
        {
            InvoiceLineItem__c newInvLineItem = new InvoiceLineItem__c();
            newInvLineItem.Invoiceid__c=qli.id;
            newInvLineItem.Amount__c = qli.ListPrice;
            newInvLineItem.Item__c = qli.PricebookEntry.ProductCode;
            newInvLineItem.Description__c= qli.PricebookEntry.name;
            newInvLineItem.Quantity__c= qli.quantity;
            
            // We need to relate the invoicelineitem to the correct invoice
            for (Invoice__c i : invoiceSet)
            {
                // Using quote number as an identifier
                if (i.Invoice_Number__c == q.quotenumber)
                {
                    newInvLineItem.Invoiceid__c= i.id;
                }
            }
            invoiceLineItemList.add(newInvLineItem);
        }
        
        // We need to remove the invoice we just used from the set, just in case there are quotes with duplicate quote numbers.
        for (Invoice__c i : invoiceSet)
        {
            if (i.name == q.name)
            {
                invoiceSet.remove(i);
            }
        }
    }
    
    insert invoiceLineItemList;

And this is my test class: 
@isTest
private class CreateInvoiceTestClass {
    @isTest static void insertOpp() {
        Account acc = new Account (name='Acme');
        insert acc;
        Opportunity opp= new Opportunity ();
        opp.name= 'Testopp';
        Opp.Accountid= acc.id;
        opp.CloseDate= date.today();
        opp.StageName= 'Qualification';
        insert opp;

Pricebook2 pb = new Pricebook2(Name = 'Standard Price Book 2009', Description = 'Price Book 2009 Products', IsActive = true );
    insert pb;
Product2 prod = new Product2(Name = 'SLA: Bronze', IsActive = true);
    insert prod;

Pricebook2 standardPB = [select id from Pricebook2 where isStandard=true];
PricebookEntry standardPBE = new PricebookEntry(Pricebook2Id = standardPB.Id, Product2Id = prod.Id, UnitPrice = 1000, IsActive = true);
    insert standardPBE;
PricebookEntry pbe = new PricebookEntry(Pricebook2Id = pb.Id, Product2Id = prod.Id, UnitPrice = 1000, IsActive = true);
    insert pbe;
        
       
        Quote q= new Quote ();
        	 q.Name= 'Testq';
        	q.OpportunityId= Opp.id;
         	q.quotetoinvoice__C= TRUE;
         	q.REP__C= 'AC' ;
        	q.BillingStreet= '123';
        	q.BillingCity= 'City';
        	q.BillingPostalCode= '12345';
        	q.Pricebook2Id= pb.id;
        	insert q;
       
      QuoteLineItem qli= new QuoteLineItem(id=q.Id, Product2id='Product', PricebookEntryid= pbe.Id,  quantity=2);
        insert qli;
        opp.StageName= 'Closed Won';

									}
    
}

Keep getting error:  System.QueryException: List has no rows for assignment to SObject,   Class.CreateInvoiceTestClass.insertOpp  line 18

Please help. 
 
Best Answer chosen by Sammy7
Sammy7Sammy7
@isTest
private class CreateInvoiceTestClass {
    @isTest static void insertOpp() {
        Account acc = new Account (name='Acme');
        insert acc;
        Opportunity opp= new Opportunity ();
        opp.name= 'Testopp';
        Opp.Accountid= acc.id;
        opp.CloseDate= date.today();
        opp.StageName= 'Qualification';
        insert opp;

Pricebook2 pb = new Pricebook2(Name = 'Standard Price Book 2009', Description = 'Price Book 2009 Products', IsActive = true );
    insert pb;
Product2 prod = new Product2(Name = 'SLA: Bronze', IsActive = true);
    insert prod;
PricebookEntry pbe=new PricebookEntry(unitprice=0.01,Product2Id=prod.Id, Pricebook2Id=Test.getStandardPricebookId(), IsActive= true); 
     insert pbe;   
       
        Quote q= new Quote ();
        	 q.Name= 'Testq';
        	q.OpportunityId= Opp.id;
         	q.quotetoinvoice__C= TRUE;
         	q.REP__C= 'AC' ;
        	q.BillingStreet= '123';
        	q.BillingCity= 'City';
        	q.BillingPostalCode= '12345';
        	q.Pricebook2Id= pb.id;
        	insert q;
       
      QuoteLineItem qli= new QuoteLineItem(id=q.id, PricebookEntryid= pbe.Id,  quantity=2);
        insert qli;
        opp.StageName= 'Closed Won';

									}
    
}

I fixed the exception error, but now gettings this: 
System.TypeException: Invalid id value for this SObject type: 0Q036000000g3VlCAI        
Class.CreateInvoiceTestClass.insertOpp: Line 37

All Answers

Sammy7Sammy7
@isTest
private class CreateInvoiceTestClass {
    @isTest static void insertOpp() {
        Account acc = new Account (name='Acme');
        insert acc;
        Opportunity opp= new Opportunity ();
        opp.name= 'Testopp';
        Opp.Accountid= acc.id;
        opp.CloseDate= date.today();
        opp.StageName= 'Qualification';
        insert opp;

Pricebook2 pb = new Pricebook2(Name = 'Standard Price Book 2009', Description = 'Price Book 2009 Products', IsActive = true );
    insert pb;
Product2 prod = new Product2(Name = 'SLA: Bronze', IsActive = true);
    insert prod;
PricebookEntry pbe=new PricebookEntry(unitprice=0.01,Product2Id=prod.Id, Pricebook2Id=Test.getStandardPricebookId(), IsActive= true); 
     insert pbe;   
       
        Quote q= new Quote ();
        	 q.Name= 'Testq';
        	q.OpportunityId= Opp.id;
         	q.quotetoinvoice__C= TRUE;
         	q.REP__C= 'AC' ;
        	q.BillingStreet= '123';
        	q.BillingCity= 'City';
        	q.BillingPostalCode= '12345';
        	q.Pricebook2Id= pb.id;
        	insert q;
       
      QuoteLineItem qli= new QuoteLineItem(id=q.id, PricebookEntryid= pbe.Id,  quantity=2);
        insert qli;
        opp.StageName= 'Closed Won';

									}
    
}

I fixed the exception error, but now gettings this: 
System.TypeException: Invalid id value for this SObject type: 0Q036000000g3VlCAI        
Class.CreateInvoiceTestClass.insertOpp: Line 37
This was selected as the best answer
Sammy7Sammy7
ok I fixed this line:
QuoteLineItem qli= new QuoteLineItem(Quoteid=q.id, PricebookEntryid= pbe.Id,  quantity=2, unitprice=10000);

Now I have no idea why this is popping up:
System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, The pricebook entry is in a different pricebook than the one assigned to the Quote, or Quote has no pricebook assigned.: [PricebookEntryId] : Line 33

Please help