+ Start a Discussion
emuelasemuelas 

Trigger to create records on unrelated objects

Hi,

 

I have a custom object product_inventory__c which has a lookup field to  product.

 

I have another custom object order_line__c which has a lookup field to  product.

 

The requirement is,every time an order line is created,i need to check in the product inventory if any record exists for that product.

 

If record  in product inventory does not exist ,I need to create a new product_inventory_record for the product.

 

 

To achieve this ,I tried writing a trigger on order_line__c object,that would create a new product_inventory record if it is not present.

 

 

 

But since product inventory and order line do not share a master detail relationship,Iam not sure how this goes.i tried writing the following sample code:

 

trigger inventory on Order_Line__c(after insert) {

 

Order_Line__c ol=trigger.new;

 

for (Order_Line__c neworder: Trigger.New) {


Integer i=[select count() from Product_Inventory__c where Product__c :=ol.Product__c];

if(i=0)
{

Product_Inventory__c.add(new Product_Inventory__c(
product__c=neworder.product));

}

}
}

 

This is erroring out of course because i have not mapped any id's....but iam not sure how to do that since i just want to compare if any record with the product is existing

Please help...

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Jeremy.NottinghJeremy.Nottingh

You have a query running inside a for loop, which is a bad idea. This will hit the governors pretty quickly. Let's fix that while we're looking at your real issue.

 

Basically, you want to go through the order lines, and for each one, check if there's already a product inventory for that order line. If not, then create one. We have to split out the querying and the inserting from the loops, which means every query and insert should be in bulk. Maybe we can do it with one of each.

 

 

Trigger inventory on Order_Line__c (after insert) {
  
  // create set of IDs for the Products we need to look for
  set<id> affectedProdidset = new set<id>();
  for (Order_Line neworder : Trigger.New) {
    affectedProdidset.add(neworder.Product__c);
  }

  //get list of existing product inventory objs to look through  
  list<product_inventory__c> prodinvs = [select id, Product__c from product_inventory__c where Product__c in :affectedProdidset];

  //go through that list and make a map to connect product id to product inventory obj
  map<id, Product_Inventory__c> prodid2pimap = new map<id, Product_Inventory__c>();
  for (Product_Inventory__c pi : prodinvs) {
    prodid2pimap.put(pi.Product__c, pi);
  }

  //now check all the product ids, and see if there are any missing
  list<Product_Inventory__c> pistoinsert = new list<Product_Inventory__c>();
  for (ID prodid : affectedProdidset) {
    //if there's no product inventory for this prodid
    if (!prodid2pimap.keyset().contains(prodid)) {
      Product_Inventory__c newpi = new Product_Inventory__c(Product__c = prodid);
      pistoinsert.add(newpi);
    }
  }

  insert pistoinsert;

 

There are other ways to do it, but see if that basically works for you. Check for typos, etc.

 

Jeremy

 

All Answers

Jeremy.NottinghJeremy.Nottingh

You have a query running inside a for loop, which is a bad idea. This will hit the governors pretty quickly. Let's fix that while we're looking at your real issue.

 

Basically, you want to go through the order lines, and for each one, check if there's already a product inventory for that order line. If not, then create one. We have to split out the querying and the inserting from the loops, which means every query and insert should be in bulk. Maybe we can do it with one of each.

 

 

Trigger inventory on Order_Line__c (after insert) {
  
  // create set of IDs for the Products we need to look for
  set<id> affectedProdidset = new set<id>();
  for (Order_Line neworder : Trigger.New) {
    affectedProdidset.add(neworder.Product__c);
  }

  //get list of existing product inventory objs to look through  
  list<product_inventory__c> prodinvs = [select id, Product__c from product_inventory__c where Product__c in :affectedProdidset];

  //go through that list and make a map to connect product id to product inventory obj
  map<id, Product_Inventory__c> prodid2pimap = new map<id, Product_Inventory__c>();
  for (Product_Inventory__c pi : prodinvs) {
    prodid2pimap.put(pi.Product__c, pi);
  }

  //now check all the product ids, and see if there are any missing
  list<Product_Inventory__c> pistoinsert = new list<Product_Inventory__c>();
  for (ID prodid : affectedProdidset) {
    //if there's no product inventory for this prodid
    if (!prodid2pimap.keyset().contains(prodid)) {
      Product_Inventory__c newpi = new Product_Inventory__c(Product__c = prodid);
      pistoinsert.add(newpi);
    }
  }

  insert pistoinsert;

 

There are other ways to do it, but see if that basically works for you. Check for typos, etc.

 

Jeremy

 

This was selected as the best answer
emuelasemuelas

Thank you Jeremy,

 

 

This was exactly what was i was looking for.The explanation was also very clear and concise for a beginner like me

Tanvi KakkarTanvi Kakkar
Hi Jeremy 
Can U please help me with this one . 
I have two objects parent__c and Teacher__c . There is no relationship between them .no materdetail no lookup . 
only name fields in both parent__c and teacher__c will be treated as common , because we will manual enter the name field . 
Parent fields: name(text )
, teacher_expertise (text)
Teacher Name (text)
Teacher fields :
- name (text)
expertise (picklist) 
Teacher_name( Text Fields)
I would like to update teacher_expertise and Teacher_name  field on parent objects :
Once we update fields on Teacher__c it should update Parent__c.
how can we use maps in this . 
Please help . Urgent
Thanks