[SalesForce] How to provide relation between a custom object and Opportunity Line Item

I have custom objects named Order and Order Line Item, just like Opportunity and Opportunity Line Item, they have same fields and relationships but Order Line Item has no need for Pricebook, products can be added directly. Also Order object has Lookup to Opportunity so every Order has a related Opportunity. What I need is when add a product to Order Line Item of the Order, same product must be added to Opportunity Line Item of the related Opportunity. I cannot give Lookup between Order Line Item and Opportunity Line Item, so don't know how get Opportunity, PriceBookEntryId values. I tried it in this trigger:

trigger CreateOpportunityProduct on Order_Line_Item__c(after insert, after update){
    List<OpportunityLineItem> OppLineList = new List<OpportunityLineItem>();
    for(Order_Line_Item__c OrderLineObj : Trigger.new){
        OpportunityLineItem OppL = new OpportunityLineItem(
            Opportunity=OrderLineObj.?,  //Opportunity field is required but I don't know how to get it. 
            PricebookEntryId=OrderLineObj.Price_Book__c,  //I done a lookup named Price_Book__c to Price Book object but I don't know if it's helps.
            UnitPrice=OrderLineObj.UnitPrice__c,
            Quantity=OrderLineObj.Quantity__c
        );
        OppLineList.add(OppL);
    }
    if(OppLineList.size()>0)
        insert(OppLineList);
}

I write this trigger now but still having some errors, how can I make it run:

trigger CreateOpportunityProduct on Order_Line_Item__c(after insert, after update){   
if(trigger.isInsert){   
   List<ID> pricebookID=new List<ID>();
   List<ID> opportunityID=new List<ID>();  
List<OpportunityLineItem> newopportunitylineitemlist=new List< OpportunityLineItem>();
    for(Order_Line_Item__c orderlist: Trigger.new){
OpportunityLineItem Oppitem=new OpportunityLineItem();
Oppitem.Quantity=orderlist.Quantity__c;
Oppitem.UnitPrice=orderlist.UnitPrice__c;
pricebookID.add(Oppitem.PriceBookEntryId); //Error: Compile Error: Invalid field PriceBookEntryId for SObject Order_Line_Item__c at line 11 column 17
opportunityID.add(Oppitem.OpportunityId); //Error: Compile Error: Invalid field OpportunityId for SObject Order_Line_Item__c at line 12 column 19
newopportunitylineitemlist.add(Oppitem);}
List<Order__c> orderlist= new List<Order__c>([Select Id,Opportunities__c From Order__c Where Opportunities__c IN:opportunityID]);   
List<PricebookEntry> pricebookentrylist = new List<PricebookEntry>([Select Id,Product2Id From PricebookEntry Where Id IN:pricebookID]); 
if(newopportunitylineitemlist.size()>0)
insert(newopportunitylineitemlist);}
}

Best Answer

You cant' make a lookup to OpportunityLineItem. Best you could do is some Text(18) field filled in with triggers. You could make the lookup from Opp Line Item to Order Line Item but it'd look bit stupid (Order -> Opportunity but Opp LI -> Ord LI).

Nonetheless - a rough idea how to fetch Opps because that's a start anyway:

  1. Fetch Orders related to line items from current trigger's scope.

    Set<Id> orderIds = new Set<Id>();
    for(Order_Line_Item__c oli : trigger.new){
        orderIds.add(oli.Order__c);
    }
    
  2. Fetch Opportunities (and Pricebook selections on them) that these Orders point to. Consult http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_erd_products.htm to understand the relations

    Map<Id, Order__c> ordersMap = new Map<Id, Order__c>([SELECT Id, Name,
        Opportunity__c, Opportunity__r.Pricebook2Id
        FROM Order__c
        WHERE Id IN :orderIds]);
    
  3. To create an Opp Line Item you need Opportunity Id:

    for(Order_Line_Item__c oli : trigger.new){
       Id oppId = ordersMap.get(oli.Order__c).Opportunity__c;
       ...
    }
    
  4. and PricebookEntryId (I'm skipping the price, quantity etc). That one will be tricky because we don't know what do you have on the line items? Lookup to Product2? What do people actually fill in? You said you've made a lookup to pricebook, but it might be bit of duplicate info (the pricebook entry you'll end up picking has to match the opportunity's pricebook or the line won't save). You will need a query similar to this:

    SELECT Id, Pricebook2Id,Product2Id
    FROM PricebookEntry
    WHERE Pricebook2Id = :ordersMap.get(oli.Order__c).Opportunity__r.Pricebook2Id
    AND Product2Id = :oli.Product__c
    

Of course if you'll store say product names on Order line items, you could go ... AND Product2.Name = 'Generator' in that last line. You might also get multiple entries for that product in the pricebook if you have multiple currencies for example...

Up to you how to go from here...