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
emuelasemuelas 

Bulkify Trigger-Help needed

Hi,

I have the following update trigger on custom object purchase_order_line__c.

Whenever a purchase_order_line__c record is updated the trigger checks for the received quantity and product serial(object) records for the product and purchase order combination and creates new product serial records for the difference in quantity.

The code works fine when one record is updated at a time .I have a visualforce page which mass updates multiple purchase_order_line__c records at a  single time.in such a  case this trigger only fires for the first record.

Please help me to bulkify this trigger.

The trigger code:

trigger createserial on Purchase_Order_Line__c (after update)
//Trigger to get fired when a purchase order line record is updated.

{
public Purchase_order_line__c[] pol = Trigger.new;
//Create a variable reference to the object fired by the trigger.
 
Integer serialcount =[select count() from product_serial__c where product__c in
 (select product__c from purchase_order_line__c where id=:pol[0].id) and purchase_order__c in
 (select purchase_order__c from  purchase_order_line__c where id=:pol[0].id )];
//Get the count of product serial records for the selected purchase_order_line
 
Decimal diff=pol[0].received_quantity__c-serialcount;
//Get the difference of records to determine if any new product serial records are to be created.
for (integer i=0 ;i<diff;i++){

Product_serial__c  obj = new Product_serial__c(
product__c=pol[0].product__c,
purchase_order__c=pol[0].purchase_order__c);
//create new product serial records

insert obj;
//insert is placed in loop so that for each iteration the record is inserted.
}
 
}

Best Answer chosen by Admin (Salesforce Developers) 
Imran MohammedImran Mohammed

Hi,

 

What you are trying to achieve is little complex. 

Your trigger should be something like this.

 

 

trigger createserial on Purchase_Order_Line__c (after update)
//Trigger to get fired when a purchase order line record is updated.
{
 List<Product_serial__c> psList = new List<Product_serial__c>();
 Map<ID, Purchase_order_line__c> polMap = Trigger.newMap();
 List<ProductSerial> pserialList =[select id, product__c, purchase_order__c from product_serial__c where product__c in
 (select product__c from purchase_order_line__c where id in :polMap.keyset()) and purchase_order__c in
 (select purchase_order__c from  purchase_order_line__c where id in :polMap.keyset())];
 Integer count = 0;
 List<Product_serial__c> newPSList = new List<Product_serial__c>();
 for(Purchase_Order_Line__c pol: Trigger.new)
 {
 count = 0;
 for(product_serial__c ps: pserialList)
 {
 if(pol.product__c == ps.product__c && pol.purchase_order__c == ps.purchase_order__c)
 count++;
 }
 Decimal diff=pol.received_quantity__c-count;
for (integer i=0 ;i<diff;i++){
Product_serial__c  obj = new Product_serial__c(
product__c=pol.product__c,
purchase_order__c=pol.purchase_order__c);
newPSList.add(obj);
}
}
insert newPSList; 
}
Let me know if you have any questions.

All Answers

EnthEnth

You've implicitly referenced only the first record by stating pol[0] in your queries. Trigger.new returns a list object and you can simply include this in your query using an IN clause. To get the count for each you can use the group by and AggregateResult object.

 

Here's a simple example that counts the number of contacts for each Account, use this to amend your trigger, if you get stuck drop a reply.

 

 

List<Account> accList = [SELECT Id from Account];

List<AggregateResult> conList = [SELECT AccountId, Count(Id) FROM Contact WHERE AccountId IN :accList GROUP BY AccountId];

for (AggregateResult con : conList) {
	System.debug(' Account ' +con.get('AccountId') + '  Count ' + con.get('expr0'));
}

The second part will be when you create your objects, you create them inside the for loop, but add them to a List of the same SObject type. Outside of your for loop call the insert on the list.

 

 

 

 

 

Imran MohammedImran Mohammed

Hi,

 

What you are trying to achieve is little complex. 

Your trigger should be something like this.

 

 

trigger createserial on Purchase_Order_Line__c (after update)
//Trigger to get fired when a purchase order line record is updated.
{
 List<Product_serial__c> psList = new List<Product_serial__c>();
 Map<ID, Purchase_order_line__c> polMap = Trigger.newMap();
 List<ProductSerial> pserialList =[select id, product__c, purchase_order__c from product_serial__c where product__c in
 (select product__c from purchase_order_line__c where id in :polMap.keyset()) and purchase_order__c in
 (select purchase_order__c from  purchase_order_line__c where id in :polMap.keyset())];
 Integer count = 0;
 List<Product_serial__c> newPSList = new List<Product_serial__c>();
 for(Purchase_Order_Line__c pol: Trigger.new)
 {
 count = 0;
 for(product_serial__c ps: pserialList)
 {
 if(pol.product__c == ps.product__c && pol.purchase_order__c == ps.purchase_order__c)
 count++;
 }
 Decimal diff=pol.received_quantity__c-count;
for (integer i=0 ;i<diff;i++){
Product_serial__c  obj = new Product_serial__c(
product__c=pol.product__c,
purchase_order__c=pol.purchase_order__c);
newPSList.add(obj);
}
}
insert newPSList; 
}
Let me know if you have any questions.
This was selected as the best answer
emuelasemuelas

Thank you so much Imran! You are a life saver.This was exactly what i needed.

Imran MohammedImran Mohammed

Any Apex code that is written should be able to  address bulk data.

You will find more info on coding bulk programs in Apex guide