I have three options to insert credits.

  • Credit option 1
  • Credit option 2
  • Credit option 3

User must always have at least one credit option but can add up to 3. The picklist options for each credit option is:

  • Self-Service
  • Emergency
  • Bonus

If Self-Service is chosen for any 3, it needs to be added to the contact’s credit field: Self-Service credit amount. I currently have this if statement but need to add two more for the two other credit options.

  if (Credits.credit_option1__c == ’Self-Service') {
        if (credits.credit_left__c == null) {
            credits.credit_left__c = 0;
        Contact con = [SELECT Id, credit_left__c FROM contact WHERE Id = :theEquipment.contact__c];
        con.Self_Service_credit__c +=credits.credits_left__c;
        update con;
   if (Credits.credit_option2__c == ’Self-Service') {
        if (credits.credit_left__c == null) {
            credits.credit_left__c = 0;
        Contact con = [SELECT Id, credit_left__c FROM contact WHERE Id = :theEquipment.contact__c];
        con.Self_Service_credit__c +=credits.credits_left_2__c;
        update con;

.......continuing to other part of class

 IF(Credit_option_1__c > maxedCredit){
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 
‘Credit cannot be higher then offered'));

Its also supposed to be less than one of our set variables maxedCredit. If one of the returns is null it throws an error since there is nothing in it. Is there a shorter way to write a null checker to check if both credit options after credit option 1 is null or it isn’t then it shouldn’t throw that error? everything would work fine if all three credit options were entered but sometimes its not necessary. Just need to be able to run it if one option is selected, or two, or all three.


A lot of the duplication can be extracted, and the remaining logic could be given dynamically:

// Set to zero if no value
if (credits.credit_left__c == null) {
    credits.credit_left__c = 0;
// Field map of Credit Type Field to Credit Value fields
Map<SObjectField, SObjectField> creditTypeToCreditValue =
    new Map<SObjectField, SObjectField> {
        Credit__c.CreditOption1__c => Credit__c.Credits_Left__c,
        Credit__C.CreditOption2__c => Credit__c.Credits_Left_2__c,
        Credit__C.CreditOption3__c => Credit__c.Credits_Left_3__c
 // Field map of Credit Types to Contact Fields
Map<String, SObjectField> creditTypeToContactField =
    new Map<String, SObjectField> {
        'Self-Service' => Contact.Self_Service_Credit__c,
        'Emergency' => Contact.Emergency_Credit__c,
        'Bonus' => Contact.Bonus_Credit__c
// Load record
Contact contactRecord = [select Self_Service_Credit__c, Emergency_Credit__c, Bonus_Credit__c 
      FROM Contact WHERE Id = :theEquipment.Contact__c];
Decimal usedCredit = 0;
for(SObjectField creditTypeField: creditTypeToCreditValue.keySet()) {
    String creditType = (String)Credits.get(creditTypeField);
    // Credit type missing or not mapped, skipping
    if(!creditTypeToContactField.containsKey(creditType)) {
    // Cache variables
    SobjectField creditValueField = creditTypeToCreditValue.get(creditTypeField),
                 contactValueField = creditTypeToContactField.get(creditType);
    Decimal creditAmount = (Decimal)Credits.get(creditValueField),
            contactAmount = (Decimal)contactRecord.get(contactValueField);
    // Avoid null pointer exception
    if(contactAmount == null) {
       contactAmount = 0;
    // Add amount
    contactAmount += creditAmount;
    usedCredit += creditAmount;
    // And put back in appropriate field
    contactRecord.put(contactValueField, contactAmount);
// Finally, see if we went over the limit
if(usedCredit > maxedCredit) {
    // Display an error
} else {
    // And update the contact otherwise
    update contactRecord;

I know this looks complicated, but it's easily extensible, which is the point. It also allows you to tweak the logic for all three branches at once instead of copy-pasting code. You might want to break this up in to a few smaller functions for legibility, but it's all about using dynamic sObject methods to minimize the overhead of checking each value separately.

This code actually checks all three credit fields against all three credit types, and updates three different contact fields, combined into a single query and a single DML operation, and can handle any combination of 0, 1, 2, or 3 values. I expect there's a little bit of work to do to clean this up, but hopefully this will get you started.

  • Thanks for posting this, but I really just need to know how to combine the credit options if only "self-Service" is chosen. only self service credit goes to contact and not the other options. the other options is only for the equipments which isn't part of this class, if that makes sense.
    – J.koh
    Jun 22 '18 at 0:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.