Scenario 1:
a) Trigger on Custom Object 'Prod' only when record type = 'Forecast'.
b) It should take data from 1 custom date field and 3 custom number fields in Object 'Prod'
c) Then creates 3 records in Custom Object 'Inv' - Each record will have that 1 date field and 1 of the custom number field from 'Prod'
Scenario 2:
a) Trigger on Custom Object 'Prod' only when record type = 'Actual'
b) It should take data from the same custom date field and 3 different custom number fields in Object 'Prod'
c) Result of this will update the 3 records in 'Inv' with the respective correct date and volume
Here is my Apex Trigger:
trigger ProductionTrigger on Prod__c (before insert, before update) {
List<Prod__c> prod_Forecast = new List<Prod__c>();
List<Prod__c> prod_Actual = new List<Prod__c>();
List<Inv__c> inv_Forecast = new List<Inv__c>();
List<Inv__c> inv_afterInsertForecast = new List<Inv__c>();
List<Inv__c> inv_toUpdateWithActuals = new List<Inv__c>();
for (Prod__c p : Trigger.new) {
//Loop through all records in the Trigger.new collection only if Production = 'Forecast'
if (p.RecordTypeId == Schema.SObjectType.Prod__c.RecordTypeInfosByName.get('Forecast').RecordTypeId) {
prod_Forecast.add(p);
} else if (p.RecordTypeId == Schema.SObjectType.Prod__c.RecordTypeInfosByName.get('Actual').RecordTypeId) {
prod_Actual.add(p);
}
}
//Only trigger for when record type = 'Forecast'
if (prod_Forecast.isEmpty() == false) {
for (Prod__c p : prod_Forecast){
if (p.A_Volume__c != 0){
Inv__c inv = new Inv__c();
inv.Inventory_Date__c = p.Production_Date__c;
inv.Product_Family__c = 'Liquid A';
inv.Product_Grade__c = 'A';
inv.Incoming_Stock__c = p.A_Volume__c;
inv_Forecast.add(inv);
}
if (p.B_Volume__c != 0) {
Inv__c inv2 = new Inv__c();
inv2.Inventory_Date__c = p.Production_Date__c;
inv2.Product_Family__c = 'Liquid B';
inv2.Product_Grade__c = 'B';
inv2.Incoming_Stock__c = p.B_Volume__c;
inv_Forecast.add(inv2);
}
if (p.C_Volume__c != 0) {
Inv__c inv3 = new Inv__c();
inv3.Inventory_Date__c = p.Production_Date__c;
inv3.Product_Family__c = 'Liquid C';
inv3.Product_Grade__c = 'C';
inv3.Incoming_Stock__c = p.C_Volume__c;
inv_Forecast.add(inv3);
}
}
if (inv_Forecast.size() > 0) {
insert inv_Forecast;
inv_afterInsertForecast = ([SELECT Id, Inventory_Date__c , Product_Family__c, Product_Grade__c, Opening_Stock__c
FROM Inv__c
WHERE id IN :inv_Forecast]);
}
}
//Only trigger for when record type = 'Actual'
if (prod_Actual.isEmpty() == false) {
for (Prod__c p : prod_Actual){
for (Inv__c i : inv_afterInsertForecast){
if (i.Inventory_Date__c == p.Production_Date__c &&
i.Product_Family__c == 'Liquid A' &&
i.Product_Grade__c == 'A' ){
Inv__c invA = new Inv__c();
invA.id = i.id;
invA.Inventory_Volume__c = p.A_Volume__c;
inv_toUpdateWithActuals.add(invA);
}
if (i.Inventory_Date__c == p.Production_Date__c &&
i.Product_Family__c == 'Liquid B' &&
i.Product_Grade__c == 'B'){
Inv__c invB = new Inv__c();
invB.id = i.id;
invB.Inventory_Volume__c = p.B_Volume__c;
inv_toUpdateWithActuals.add(invB);
}
if (i.Inventory_Date__c == p.Production_Date__c &&
i.Product_Family__c == 'Liquid C' &&
i.Product_Grade__c == 'C'){
Inv__c invC = new Inv__c();
invC.id = i.id;
invC.Inventory_Volume__c = p.B_Volume__c;
inv_toUpdateWithActuals.add(invC);
}
}
}
if (inv_toUpdateWithActuals.size() > 0) {
update inv_toUpdateWithActuals;
}
}
}
Unexpected outcomes from my code
It can accomplish Scenario 1 by creating 3 records in Inv__c but somehow also creates records in Prod__c for ALL Prod__c record types.
It doesn't update the 3 records in inventory at all even when I mapped the Inventory_Date__c, Product_family__c and Product_group__c.
Help please?
****UPDATE**** Also a few side questions (besides the fact I need to make handlers to minimize the codebase in triggers) :
1) Are my parameters correct that I did before insert, before update on the 1st line of my code? (was thinking scenario 2 would be after insert, after update)
2) How could I have done this differently using Map, Set?
3) I tried to separate both scenarios using Trigger.IsBefore/ Trigger.isUpdate/ Trigger.isInsert but had an inkling that separating by record types should be good enough
Inv__c
creation uses a fieldInventory_Date__c
, but your update usesPlan_Date__c
. Is the latter derived from the former? I don't completely follow your point 1 about creating for all record types - aren't you creatingInv__c
records, notProd__c
?