[SalesForce] How to iterate over all Opptys and their line items- in bulk with map

While in a trigger,
I want to iterate over all Opportunities (opptys) and their related OpportunityLineItems (olis).
This is the pseudo code I use, and problem I face is how do I iterate over all the olis, while already looping in the oppty FOR loop

 //prepare the list of oppties ids
   Id[] oppids = new Id[]{};
   for(Opportunity opp : Trigger.new) {
   oppids.add(opp.Id);
   }

Now to create a map of all the opptys and their olis:
I am not sure this is correct map, or should it be opportunitylineitem object.

 map<id, Opportunity> opptys = new Map<ID, Opportunity>([SELECT Id, (SELECT id, 
         Discount, listprice, name, 
         opportunityid, Product2Id, unitprice, 
         Quantity,totalprice FROM opportunityLineItems) FROM Opportunity WHERE Id in :oppids]);

This is the FOR loop

for(Opportunity opp : Trigger.new) {

And while in the loop, I want to go over all the olis.

Current code is:

for ( OpportunityLineItem oli : opptys.get(opp.Id) )
        {
            .....
            jsGen.writeNumberField('ListPrice', oli.ListPrice);
            ....
        }

which throws an error that

Loop must iterate over a collection type: SOBJECT:Opportunity

Which is understood, as I have a map of opptys.

However, if I change the for to be of opptys:

for ( Opportunity oli : opptys.get(opp.Id) )
        {
            .....
            jsGen.writeNumberField('ListPrice', oli.ListPrice);
            ....
        }

The error is (and correct) that ListPrice is NOT a field in Opportunity – which is true. But ListPrice field is in the MAP (the select has this field)

Also, the smarttext shows ListPrice – as of OpportunityLineItemField

enter image description here

So My Loops/For/Maps are misplaced somewhere, how do I iterate over them ?

Best Answer

Since opportunityLineItems is a level 'deeper' then opportunity, you need to do an inner loop through the opportunityLineItems of the Opportunity that your have picked from the map:

for ( Opportunity o : opptys.get(opp.Id) )
        {

            for ( OpportunityLineItem oli : o.OpportunityLineItems) )
                {
                    .....
                    jsGen.writeNumberField('ListPrice', oli.ListPrice);
                    ....       
                }
            ....
        }