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
Smike25Smike25 

Help with writing Trigger to update default value of master-detail relationship

Looking for some help on writing my first trigger.  I have two custom objects ( Payroll [Payroll__c] and Commissions [Commissions__c] ).  The commissions object has the Master-Detail(Payroll) rollup field (Bonus Program [Bonus_Program__c]).

Payroll has two records record ID's in it, but i'm only concerned with one of them.  Any commission record created now will be eligible for a Bonus, and needs to be stamped with the Bonus record ID from Payroll (a0s230000008Rft).  The other ID contains all the records that were not eligible for a bonus.  I have a process that automatically creates a commission record based upon certain criteria, however now the process wont fire due to the "Bonus_Program__c" field being blank.  I can't seem to use process builder to automaticcaly assign the ID, so i'm looking at trying to create the trigger.  I've been trying some of the help posts through the community, but no luck so far getting much of anywhere.  
Best Answer chosen by Smike25
pconpcon
So you just want to populate the Payroll__c field with the record Id of the Bonus everytime a Commissions__c record is inserted?

Easiest
trigger BonusMapping on Commissions__c (before insert) {
    Id bonusRecordId = 'a0s230000008Rft';

    for (Commissions__c c : Trigger.new) {
        c.Payroll__c = bonusRecordId;
    }
}

Better
trigger BonusMapping on Commissions__c (before insert) {
    List<Payroll__c> bonus = [
        select Id
        from Payroll__c
        where Name = 'Bonus'
    ];

    if (!bonus.isEmpty()) {
        Id bonusRecordId = bonus.get(0).Id;

        for (Commissions__c c : Trigger.new) {
            c.Payroll__c = bonusRecordId;
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

The second trigger is safer because it does not use a hardcoded Id and would still work in a sandbox as long as someone creates a Payroll record with a name of Bonus.

All Answers

pconpcon
So you just want to populate the Payroll__c field with the record Id of the Bonus everytime a Commissions__c record is inserted?

Easiest
trigger BonusMapping on Commissions__c (before insert) {
    Id bonusRecordId = 'a0s230000008Rft';

    for (Commissions__c c : Trigger.new) {
        c.Payroll__c = bonusRecordId;
    }
}

Better
trigger BonusMapping on Commissions__c (before insert) {
    List<Payroll__c> bonus = [
        select Id
        from Payroll__c
        where Name = 'Bonus'
    ];

    if (!bonus.isEmpty()) {
        Id bonusRecordId = bonus.get(0).Id;

        for (Commissions__c c : Trigger.new) {
            c.Payroll__c = bonusRecordId;
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

The second trigger is safer because it does not use a hardcoded Id and would still work in a sandbox as long as someone creates a Payroll record with a name of Bonus.
This was selected as the best answer
Smike25Smike25
Went with option #1.  We should never need the commissions record created to ever be anything different from that ID.  I edited line 5 to read "c.Bonus_Program__c = bonusRecordId;" and it created the record and inserted the ID perfectly.  Thank you pcon!
pconpcon
You should really think about doing #2 because you should be writing your tests without seeAllData and you should insert the the bonus payroll object as part of your test.
Smike25Smike25
Went ahead and modified it to work so I actually have both (2nd one active).  It creates perfectly with the new record name of "Bonus".  Thank for your assistance on it.  The tougher part for me will be the test coverage now!
Smike25Smike25
For the first one, I made this simple test class which covered 100%:
  1. @isTest
  2. public class TestBonusMapping {
  3.     static testmethod void insertCommission()  {
  4.        
  5.         Commissions__c c = new Commissions__c();
  6.         
  7.         c.Bonus_Program__c = 'a0s230000008Rft';
  8.        
  9.         insert c;
  10.         
  11.         }
  12.         }
For the second one, i'm not sure where to start since i've never made a trigger with List<> command.  Suggestions on where to start on that one?  Code coverage states 40% using the same test as trigger 1, but i'm not defining anything through Payroll__c.
pconpcon
That test doesn't actually test what you are expecting it to and I suspect that it will likely not get the same coverage amount when you push it to a production instance.  What you should do is:
 
static testMethod void BonusMappingTest {
    Payroll__c testPayroll = new Payroll__c (
        Name = 'Bonus'
    );
    insert testPayroll;

    Commission__c testCommission = new Commission__c();

    Test.startTest();

    insert testCommission;

    Test.stopTest();

    testCommission = [
        select Bonus_Program__c
        from Comission__c
        where Id = :testCommission.Id
    ];

    System.assertEquals(
        testPayroll.Id,
        testCommission.Bonus_Program__c,
        'Did not get the right bonus program assigned'
    );
}

This test creates the data you need for your test, then inside a start/stop test it inserts the Commission__c object.  Then we fetch our data back and assert our trigger did the right thing.  If you are using API version 24+ you will need to create all data inside of your test that you need for you classes / triggers.  Unless you have a valid reason you should be using the current API version (35) for your triggers.
Smike25Smike25
I'm using API 35.  Getting 
Error: Compile Error: unexpected token: static at line 1 column 0 when attempting to save the class. 
pconpcon
That's because the code I provided is only the test method and does not include the test class definition.  You need to place it inside your test class before you save it.
Smike25Smike25
Thanks for you help with this pcon.  I'm still struggling on what to include and not able to find info online to better assist me in trying to understand it.  At this point im getting

"Error: Compile Error: sObject type 'Commission__c' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names. at line 18 column 22"

With code:
@isTest
public class myClass {
static testMethod void BonusMappingTest() {

    Payroll__c testPayroll = new Payroll__c (
        Name = 'Bonus'
    );
    insert testPayroll;

    Commission__c testCommission = new Commission__c();

    Test.startTest();

    insert testCommission;

    Test.stopTest();

    testCommission = [
        select Bonus_Program__c
        from Commission__c
        where Id = :testCommission.Id
    ];

    System.assertEquals(
        testPayroll.Id,
        testCommission.Bonus_Program__c,
        'Did not get the right bonus program assigned'
    );
}
}

 
pconpcon
That's my fault.  Everywhere I have Commission__c it should be Commissions__c
Smike25Smike25
Not your fault at all man, I should've been able to see that.  pcon, again... thank you!