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
Michael MMichael M 

Trigger- keep current record the same, but insert new record with updates

Hi, We have a daily scheduled import (from a 3rd party app) of several records to a custom object. The import is set as an "upsert". I need to add a trigger that adds one more condition to decide whether to insert or update. Specifically, if a field called "discharge_date__c" is more than 5 days apart from the existing record, I want to INSERT the new record rather than UPDATING the previous one. The error I am receiving is " System.FinalException: Record is read-only". I need a way to bypass this error. Any suggestions are greatly appreciated.Here is my current Trigger and Class.:

TRIGGER:
trigger DischargeTrigger2 on Discharge__c (after update) {
     if(system.isFuture()) return;
    
//insert new Discharge record..  
      for (Discharge__c dis : trigger.new){
          if (dis.Discharge_Date__c != null && trigger.oldMap.get(dis.Id).Discharge_Date__c !=null){
    date oldDd = trigger.oldMap.get(dis.Id).Discharge_Date__c;
    date newDd = dis.Discharge_Date__c;
    Integer difDate = oldDd.daysBetween(newDd); 
    Integer diffDate = newDd.daysBetween(oldDd);
        if (difDate > 5 || diffDate > 5){
          Discharge2Class.generateNewDischarge(dis.id);
        }}
  }
    
//If Discharge Date is more than 5 days apart from existing record, leave existing record alone and create new record, with instance counter and link to existing record
for (Discharge__c dis : trigger.new){
    if (dis.Discharge_Date__c != null && trigger.oldMap.get(dis.Id).Discharge_Date__c !=null){
    date oldDd = trigger.oldMap.get(dis.Id).Discharge_Date__c;
    date newDd = dis.Discharge_Date__c;
    Integer difDate = oldDd.daysBetween(newDd); 
    Integer diffDate = newDd.daysBetween(oldDd);
        if (difDate > 5 || diffDate > 5){
            //Prevent changing existing record
            dis.Action_Code_ID__c = trigger.oldMap.get(dis.Id).Action_Code_ID__c;
            dis.Address__c = trigger.oldMap.get(dis.Id).Address__c;
            dis.City__c = trigger.oldMap.get(dis.Id).City__c;
            dis.Date_of_Birth__c = trigger.oldMap.get(dis.Id).Date_of_Birth__c;
            dis.Discharge_Date__c = trigger.oldMap.get(dis.Id).Discharge_Date__c;
            dis.name = trigger.oldMap.get(dis.Id).name;
            dis.State__c = trigger.oldMap.get(dis.Id).State__c;
            dis.Status_Code_ID__c = trigger.oldMap.get(dis.Id).Status_Code_ID__c;
            dis.Zip__c = trigger.oldMap.get(dis.Id).Zip__c;
            dis.Progress_Notes__c = trigger.oldMap.get(dis.Id).Progress_Notes__c;
        }
    }
}
}

CLASS:
public class Discharge2Class {
 @future(callout = true)
    public static void generateNewDischarge(id i){    
        
        Discharge__c disch = [select id,Action_Code_ID__c,Address__c,City__c,Date_of_Birth__c,
                              Discharge_Date__c, State__c,Status_Code_ID__c,Zip__c,Progress_Notes__c
                              from Discharge__c where id =: i];
       
        Discharge__c newDis = new Discharge__c();
            newdis.Action_Code_ID__c = disch.Action_Code_ID__c;
            newdis.Address__c = disch.Address__c;
            newdis.City__c = disch.City__c;
            newdis.Date_of_Birth__c = disch.Date_of_Birth__c;
            newdis.Discharge_Date__c = disch.Discharge_Date__c;
            newdis.Discharge_Location_Type__c =disch.Discharge_Location_Type__c;
            newdis.Discharge_Location__c =disch.Discharge_Location__c ;
            newdis.Facility_ID__c = disch.Facility_ID__c;
            newdis.Facility_Name__c = disch.Facility_Name__c;
            newdis.name = disch.name;
            newdis.State__c = disch.State__c;
            newdis.Status_Code_ID__c = disch.Status_Code_ID__c;
            newdis.Zip__c = disch.Zip__c;
            newdis.Progress_Notes__c = disch.Progress_Notes__c;
        insert newDis;
        
    }
}
Best Answer chosen by Michael M
PRAKASH JADA 13PRAKASH JADA 13
Hey, the above will work after the update but if you want to keep the values from the insert and if you want to create the new record when the date difference is 5 days then use the below code.

Trigger:
-------------------
trigger DischargeTrigger on Discharge__c (before update) {
    // After event
    if(Trigger.isBefore) {
        if(Trigger.isUpdate) {
            DischargeHandler.onAfterSave(Trigger.New, Trigger.oldMap);
        }
    }
}


Apex class:
----------------------
public with sharing class DischargeHandler {
    // Trigger handler Method to call from the Trigger
    public static void onAfterSave(List<Discharge__c> dischargeList, Map<Id, Discharge__c> oldDischargeMap) {
        System.debug('Discharge List : ' + dischargeList.size());
        
        List<Discharge__c> newDischargeList = new List<Discharge__c>(); // List to perform the DML operation
        Integer dateDiff;
        // Loop to Iterate over the records that were updated
        for(Discharge__c discharge : dischargeList) {
            dateDiff = oldDischargeMap.get(discharge.Id).Discharge_Date__c.daysBetween(discharge.Discharge_Date__c); // To calculate the days
            System.debug('Date difference : ' +dateDiff);
            
            // Condition to check for the days count
            if( dateDiff > 5 ) {
                Discharge__c newDischarge                                 =     new Discharge__c();
                
                // Assign all the field over here
                newDischarge.Address__c                                 =    discharge.Address__c;
                newDischarge.City__c                                     =    discharge.City__c;
                newDischarge.Date_of_Birth__c                             =    discharge.Date_of_Birth__c;
                newDischarge.Discharge_Date__c                             =    discharge.Discharge_Date__c; // It will put the updated value here
                newDischarge.Discharge_Location_Type__c                 =    discharge.Discharge_Location_Type__c;
                newDischarge.Discharge_Location__c                         =    discharge.Discharge_Location__c ;
                newDischarge.Facility_ID__c                             =    discharge.Facility_ID__c;
                newDischarge.Facility_Name__c                             =    discharge.Facility_Name__c;
                newDischarge.name                                         =    discharge.name;
                newDischarge.State__c                                     =    discharge.State__c;
                newDischarge.Status_Code_ID__c                             =    discharge.Status_Code_ID__c;
                newDischarge.Zip__c                                     =    discharge.Zip__c;
                newDischarge.Progress_Notes__c                             =    discharge.Progress_Notes__c;
                newDischarge.Medicaid_ID__c                             =    discharge.Medicaid_ID__c;
                newDischarge.Medicare_ID__c                             =    discharge.Medicare_ID__c;
                newDischarge.Other_Diagnosis_ICD_Codes__c                 =    discharge.Other_Diagnosis_ICD_Codes__c;
                newDischarge.Other_Diagnosis_ICD_Descriptions__c         =    discharge.Other_Diagnosis_ICD_Descriptions__c;
                newDischarge.Patient_ID_PCC__c                             =    discharge.Patient_ID_PCC__c;
                newDischarge.Primary_Diagnosis_ICD_Code__c                 =    discharge.Primary_Diagnosis_ICD_Code__c;
                newDischarge.Primary_Diagnosis_ICD_Description__c         =    discharge.Primary_Diagnosis_ICD_Description__c;
            }//IF ENDS
            
        }// FOR ENDS
        
        // Loop to iterate over the List of updating records
        for(Discharge__c discharge : dischargeList) {
            dateDiff = oldDischargeMap.get(discharge.Id).Discharge_Date__c.daysBetween(discharge.Discharge_Date__c); // To calculate the days
            System.debug('Date difference : ' +dateDiff);
            
            // Condition to check for the days count
            if( dateDiff > 5 ) {
                // Assigning the values from Insert scenario
                discharge.Address__c                                 =     oldDischargeMap.get(discharge.Id).Address__c;
                discharge.City__c                                     =     oldDischargeMap.get(discharge.Id).City__c;
                discharge.Date_of_Birth__c                            =     oldDischargeMap.get(discharge.Id).Date_of_Birth__c;
                discharge.Discharge_Date__c                         =     oldDischargeMap.get(discharge.Id).Discharge_Date__c; 
                discharge.Discharge_Location_Type__c                 =    oldDischargeMap.get(discharge.Id).Discharge_Location_Type__c;
                discharge.Discharge_Location__c                     =     oldDischargeMap.get(discharge.Id).Discharge_Location__c ;
                discharge.Facility_ID__c                             =     oldDischargeMap.get(discharge.Id).Facility_ID__c;
                discharge.Facility_Name__c                             =     oldDischargeMap.get(discharge.Id).Facility_Name__c;
                discharge.name                                         =     oldDischargeMap.get(discharge.Id).name;
                discharge.State__c                                     =     oldDischargeMap.get(discharge.Id).State__c;
                discharge.Status_Code_ID__c                         =     oldDischargeMap.get(discharge.Id).Status_Code_ID__c;
                discharge.Zip__c                                     =     oldDischargeMap.get(discharge.Id).Zip__c;
                discharge.Progress_Notes__c                         =     oldDischargeMap.get(discharge.Id).Progress_Notes__c;
                discharge.Medicaid_ID__c                             =     oldDischargeMap.get(discharge.Id).Medicaid_ID__c;
                discharge.Medicare_ID__c                             =     oldDischargeMap.get(discharge.Id).Medicare_ID__c;
                discharge.Other_Diagnosis_ICD_Codes__c                 =     oldDischargeMap.get(discharge.Id).Other_Diagnosis_ICD_Codes__c;
                discharge.Other_Diagnosis_ICD_Descriptions__c         =     oldDischargeMap.get(discharge.Id).Other_Diagnosis_ICD_Descriptions__c;
                discharge.Patient_ID_PCC__c                         =     oldDischargeMap.get(discharge.Id).Patient_ID_PCC__c;
                discharge.Primary_Diagnosis_ICD_Code__c             =     oldDischargeMap.get(discharge.Id).Primary_Diagnosis_ICD_Code__c;
                discharge.Primary_Diagnosis_ICD_Description__c         =     oldDischargeMap.get(discharge.Id).Primary_Diagnosis_ICD_Description__c;
            }
        }
        try {
            // check to see if the list is empty before performing the DML operation
            if(!newDischargeList.isEmpty()) {
                insert newDischargeList;
            }
        }catch(DMLException e) {
            System.debug('Unable to insert the Account record : ' + e.getMessage());
        }
    }
}


This is working for me.

What it will do.

Create a new record
Name = Prakash
Discharge Date = today
Save the record

Update the same record and change the discharge from today to today + 5
then 

Update record will save with 
Name = Prakash
Discharge Date = today

Create a new record
Name = Prakash
Discharge Date = today + 5


This is the test performed. If this is the same case then you can use the above code.


Thanks,

All Answers

PRAKASH JADA 13PRAKASH JADA 13

The issue is due to the SOQL that you wrote on the object after update the record will be locked for 10 sec. If you try to access that record then the system will throw you that error message. with trigger.New you will get the all the data that related to that record and in your code your are not pulling child record data so you don't need a query. 
Trigger:
------------------

trigger DischargeTrigger2 on Discharge__c (after update) {
    if(Trigger.isAfter){
       if(Trigger.isUpdate){
        Discharge2Class.generateNewDischarge(Trigger.New);
       }
   }
}


Apex class:
------------------------
public class Discharge2Class {
 @future(callout = true)
    public static void generateNewDischarge(List<Discharge__c> dischargeList){    

       List<Discharge__c> newDischargeList = new List<Discharge__c>();

       for(Discharge__c dis : dischargeList) {

             if (dis.Discharge_Date__c > dis.Discharge_Date__c+5 ){
                   Discharge__c newDis = new Discharge__c();
                   newdis.Action_Code_ID__c = dis.Action_Code_ID__c;
                   newdis.Address__c = dis.Address__c;
                   newdis.City__c = dis.City__c;
                   newdis.Date_of_Birth__c = dis.Date_of_Birth__c;
                  newdis.Discharge_Date__c = dis.Discharge_Date__c;
                 newdis.Discharge_Location_Type__c =dis.Discharge_Location_Type__c;
                 newdis.Discharge_Location__c =dis.Discharge_Location__c ;
                 newdis.Facility_ID__c = dis.Facility_ID__c;
                 newdis.Facility_Name__c = dis.Facility_Name__c;
                 newdis.name = dis.name;
                 newdis.State__c = disch.State__c;
                 newdis.Status_Code_ID__c = dis.Status_Code_ID__c;
                 newdis.Zip__c = dis.Zip__c;
                 newdis.Progress_Notes__c = dis.Progress_Notes__c;
               newDischargeList.add(newdis);
             }      
      }
try{
     if(!newDischargeList.isEmpty()) {
        insert newDischargeList;
    }
}catch(DMLException e) {
   System.debug('Unable to Insert the Discharge Records : '+e.getMessage());
}
  }
}


In this way you can do your logic.

Michael MMichael M
Hi Prakash,
A couple points:
1. With that code, it is giving me this error: "Future methods do not support parameter type of List<Discharge__c>". 
2. Will this keep the original Discharge record the same? I want the original record to stay the same, and I just want the updates to be applied to the newly created/inserted record? 
Thank you so much for your help. 
PRAKASH JADA 13PRAKASH JADA 13
Sorry my bad you don’t need future anymore remove that and test it I. Your test org.
Michael MMichael M
Now it creates 2 new records, which are both duplicates of the original with the changes. I only need 1 new record, and I want the original record to keep its OLD values, and the new values only applied to a new record. 
PRAKASH JADA 13PRAKASH JADA 13

In the handler change the values that you need. check the mapping I used in the code and you can easily correct it. we are using on after update so it won't update the old record. 

For testing:
Edit the existing record and change the discharge date and save it so it should create the new one. 


To stop duplicates you can do like this


Trigger:
-------------
trigger DischargeTrigger2 on Discharge__c (after update) {
    if(Trigger.isAfter){
       if(Trigger.isUpdate){
        Discharge2Class.generateNewDischarge(Trigger.New, Trigger.oldMap);
       }
   }
}


Apex class:
---------------------
public class Discharge2Class {
    public static void generateNewDischarge(List<Discharge__c> dischargeList, Map<Id, Discharge__c> oldMap){    

       List<Discharge__c> newDischargeList = new List<Discharge__c>();

       for(Discharge__c dis : dischargeList) {

             if (dis.Discharge_Date__c > dis.Discharge_Date__c+5  && oldMap.get(dis.Id).Discharge_Date__c != dis.Discharge_Date__c){ // Changed line
                   Discharge__c newDis = new Discharge__c();
                   newdis.Action_Code_ID__c = dis.Action_Code_ID__c;
                   newdis.Address__c = dis.Address__c;
                   newdis.City__c = dis.City__c;
                   newdis.Date_of_Birth__c = dis.Date_of_Birth__c;
                  newdis.Discharge_Date__c = dis.Discharge_Date__c; // you need to correct the right hand side to get the new values.
                 newdis.Discharge_Location_Type__c =dis.Discharge_Location_Type__c;
                 newdis.Discharge_Location__c =dis.Discharge_Location__c ;
                 newdis.Facility_ID__c = dis.Facility_ID__c;
                 newdis.Facility_Name__c = dis.Facility_Name__c;
                 newdis.name = dis.name;
                 newdis.State__c = disch.State__c;
                 newdis.Status_Code_ID__c = dis.Status_Code_ID__c;
                 newdis.Zip__c = dis.Zip__c;
                 newdis.Progress_Notes__c = dis.Progress_Notes__c;
               newDischargeList.add(newdis);
             }      
      }
try{
     if(!newDischargeList.isEmpty()) {
        insert newDischargeList;
    }
}catch(DMLException e) {
   System.debug('Unable to Insert the Discharge Records : '+e.getMessage());
}
  }
}


By this example, you can work out on your logic. Hope this helps you to build your logic.

Michael MMichael M
I used this code, and nothing happens. The updates save, and no new record is created... 
PRAKASH JADA 13PRAKASH JADA 13
did you changed the discharge date because we have a condition on that it should not be the same on update if you simply edit and save then it won't create the new record?
Michael MMichael M
Correction: 2 new records are created, but the edited record also accepts the updates and does not go back to its old values. 

Here is the exact code I'm using:
TRIGGER:
trigger DischargeTrigger2 on Discharge__c (after update) {
     if(system.isFuture()) return;
    if(Trigger.isAfter){
       if(Trigger.isUpdate){
           for (Discharge__c dis : trigger.new){
               if (dis.Discharge_Date__c != null && trigger.oldMap.get(dis.Id).Discharge_Date__c !=null){
    date oldDd = trigger.oldMap.get(dis.Id).Discharge_Date__c;
    date newDd = dis.Discharge_Date__c;
    Integer difDate = oldDd.daysBetween(newDd); 
    Integer diffDate = newDd.daysBetween(oldDd);
        if (difDate > 5 || diffDate > 5){
        Discharge2Class.generateNewDischarge(Trigger.New, Trigger.oldMap);
       }
               }}}}  

CLASS:

public class Discharge2Class {
    public static void generateNewDischarge(List<Discharge__c> dischargeList, Map<Id, Discharge__c> oldMap){    
        
       List<Discharge__c> newDischargeList = new List<Discharge__c>();

       for(Discharge__c dis : dischargeList) {


                   Discharge__c newDis = new Discharge__c();
                   newdis.Action_Code_ID__c = dis.Action_Code_ID__c;
                   newdis.Address__c = dis.Address__c;
                   newdis.City__c = dis.City__c;
                   newdis.Date_of_Birth__c = dis.Date_of_Birth__c;
                  newdis.Discharge_Date__c = dis.Discharge_Date__c; // you need to correct the right hand side to get the new values.
                 newdis.Discharge_Location_Type__c =dis.Discharge_Location_Type__c;
                 newdis.Discharge_Location__c =dis.Discharge_Location__c ;
                 newdis.Facility_ID__c = dis.Facility_ID__c;
                 newdis.Facility_Name__c = dis.Facility_Name__c;
                 newdis.name = dis.name;
                 newdis.State__c = dis.State__c;
                 newdis.Status_Code_ID__c = dis.Status_Code_ID__c;
                 newdis.Zip__c = dis.Zip__c;
                 newdis.Progress_Notes__c = dis.Progress_Notes__c;
                 
            newdis.Medicaid_ID__c = dis.Medicaid_ID__c;
            newdis.Medicare_ID__c = dis.Medicare_ID__c;
            newdis.Other_Diagnosis_ICD_Codes__c =dis.Other_Diagnosis_ICD_Codes__c;
            newdis.Other_Diagnosis_ICD_Descriptions__c = dis.Other_Diagnosis_ICD_Descriptions__c;
            newdis.Patient_ID_PCC__c = dis.Patient_ID_PCC__c;
            newdis.Primary_Diagnosis_ICD_Code__c =dis.Primary_Diagnosis_ICD_Code__c;
            newdis.Primary_Diagnosis_ICD_Description__c =dis.Primary_Diagnosis_ICD_Description__c;
               newDischargeList.add(newdis);
          
      }
try{
     if(!newDischargeList.isEmpty()) {
        insert newDischargeList;
    }
}catch(DMLException e) {
   System.debug('Unable to Insert the Discharge Records : '+e.getMessage());
}
  }
}
Michael MMichael M
Again, I need this to accomplish 2 things:
1. do NOT apply the updates being made to the current record. Instead, keep the OLD values of the current record.
2. Create a new record with the updates that were trying to be made to the original record. 
PRAKASH JADA 13PRAKASH JADA 13
1. okay updating the old record should not happen with the above code if you know the field put a field history tracking and check for the name. 
2.  print the list that you are inserting check how many records are there and check for the created by for those 2 records if there are any other active triggers related to this please stop for this testing.
If that is the case merger your code to that trigger. You don't need duplicate logic.
Michael MMichael M
1. This was my attempt to keep the old record the same. But it gave me an error that it was read-only so I cannot update them.
trigger DischargeTrigger2 on Discharge__c (after update) {
     if(system.isFuture()) return;
        //insert new Discharge record..  
    if(Trigger.isAfter){
       if(Trigger.isUpdate){
           for (Discharge__c dis : trigger.new){
               if (dis.Discharge_Date__c != null && trigger.oldMap.get(dis.Id).Discharge_Date__c !=null){
    date oldDd = trigger.oldMap.get(dis.Id).Discharge_Date__c;
    date newDd = dis.Discharge_Date__c;
    Integer difDate = oldDd.daysBetween(newDd); 
    Integer diffDate = newDd.daysBetween(oldDd);
        if (difDate > 5 || diffDate > 5){
        Discharge2Class.generateNewDischarge(Trigger.New, Trigger.oldMap);
       }
               }}}}  

    
//If Discharge Date is more than 5 days apart from existing record, leave existing record alone and create new record, with instance counter and link to existing record
for (Discharge__c dis : trigger.new){
    if (dis.Discharge_Date__c != null && trigger.oldMap.get(dis.Id).Discharge_Date__c !=null){
    date oldDd = trigger.oldMap.get(dis.Id).Discharge_Date__c;
    date newDd = dis.Discharge_Date__c;
    Integer difDate = oldDd.daysBetween(newDd); 
    Integer diffDate = newDd.daysBetween(oldDd);
        if (difDate > 5 || diffDate > 5){
   //Prevent changing existing record
            dis.Action_Code_ID__c = trigger.oldMap.get(dis.Id).Action_Code_ID__c;
            dis.Address__c = trigger.oldMap.get(dis.Id).Address__c;
            dis.City__c = trigger.oldMap.get(dis.Id).City__c;
            dis.Date_of_Birth__c = trigger.oldMap.get(dis.Id).Date_of_Birth__c;
            dis.Discharge_Date__c = trigger.oldMap.get(dis.Id).Discharge_Date__c;
            dis.Discharge_Location_Type__c = trigger.oldMap.get(dis.Id).Discharge_Location_Type__c;
            dis.Discharge_Location__c = trigger.oldMap.get(dis.Id).Discharge_Location__c;
            dis.Facility_ID__c = trigger.oldMap.get(dis.Id).Facility_ID__c;
            dis.Facility_Name__c = trigger.oldMap.get(dis.Id).Facility_Name__c;
            //dis.First_Name__c = trigger.oldMap.get(dis.Id).First_Name__c;
            //dis.Last_Name__c = trigger.oldMap.get(dis.Id).Last_Name__c;
            //dis.name = trigger.oldMap.get(dis.Id).name;
            dis.Medicaid_ID__c = trigger.oldMap.get(dis.Id).Medicaid_ID__c;
            dis.Medicare_ID__c = trigger.oldMap.get(dis.Id).Medicare_ID__c;
            dis.Other_Diagnosis_ICD_Codes__c = trigger.oldMap.get(dis.Id).Other_Diagnosis_ICD_Codes__c;
            dis.Other_Diagnosis_ICD_Descriptions__c = trigger.oldMap.get(dis.Id).Other_Diagnosis_ICD_Descriptions__c;
            dis.Patient_ID_PCC__c = trigger.oldMap.get(dis.Id).Patient_ID_PCC__c;
            dis.Primary_Diagnosis_ICD_Code__c = trigger.oldMap.get(dis.Id).Primary_Diagnosis_ICD_Code__c;
            dis.Primary_Diagnosis_ICD_Description__c = trigger.oldMap.get(dis.Id).Primary_Diagnosis_ICD_Description__c;
            dis.Primary_Phone_PCC__c = trigger.oldMap.get(dis.Id).Primary_Phone_PCC__c;
            dis.SSN__c = trigger.oldMap.get(dis.Id).SSN__c;
            dis.State__c = trigger.oldMap.get(dis.Id).State__c;
            dis.Status_Code_ID__c = trigger.oldMap.get(dis.Id).Status_Code_ID__c;
            dis.Zip__c = trigger.oldMap.get(dis.Id).Zip__c;
            dis.Progress_Notes__c = trigger.oldMap.get(dis.Id).Progress_Notes__c; 
        }
    }
}  

}
What am I doing wrong? 

2. there are no other triggers on this object that insert new records. 
PRAKASH JADA 13PRAKASH JADA 13
please know that if there are any logics like workflow or process builders or formulas for that object because you are simply editing and changing the discharge I guess there are some other functionalities that trigger the record to update. enable the debug logs for you and add system.debugs that would help you to understand what is happening.
PRAKASH JADA 13PRAKASH JADA 13
there is a query on your initial logic that is causing the issue. 
Michael MMichael M
There aren't any workflows. This is an after update trigger, so I think that is the problem. Meaning, that is why the fields remain updated on the original record. First those update, and only afterwards does the trigger tell it to insert a new record with the same values. I need to keep the original record the same... 
Michael MMichael M
I'm not using that query in this current code... 
PRAKASH JADA 13PRAKASH JADA 13
Hi,


I used my environment to create the same as and worked on this and it is working for me without updating the old record and it is creating the new record. 
It should work for you as well. If I added the debugs as well.


Trigger:
------------------
trigger DischargeTrigger on Discharge__c (after update) {
    // After event
    if(Trigger.isAfter) {
        if(Trigger.isUpdate) {
            DischargeHandler.onAfterSave(Trigger.New, Trigger.oldMap);
        }
    }
}



Handler:
------------------------

/*
* Author: Prakash
* Created Date : Feb 13, 2020
* Based on Days count the system will insert the new record from old record but it should not update the old record.
*/


public with sharing class DischargeHandler {
    // Trigger handler Method to call from the Trigger
    public static void onAfterSave(List<Discharge__c> dischargeList, Map<Id, Discharge__c> oldDischargeMap) {
        System.debug('Discharge List : ' + dischargeList.size());
        
        List<Discharge__c> newDischargeList = new List<Discharge__c>(); // List to perform the DML operation
        
        // Loop to Iterate over the records that were updated
        for(Discharge__c discharge : dischargeList) {
            Integer dateDiff = oldDischargeMap.get(discharge.Id).Discharge_Date__c.daysBetween(discharge.Discharge_Date__c); // To calculate the days
            System.debug('Date difference : ' +dateDiff);
            
            // Condition to check for the days count
            if( dateDiff > 5 ) {
                Discharge__c newDischarge                             =     new Discharge__c();
                
                // Assign all the field over here
                newDischarge.Address__c                             =     discharge.Address__c;
                newDischarge.City__c                                 =     discharge.City__c;
                newDischarge.Date_of_Birth__c                         =     discharge.Date_of_Birth__c;
                newDischarge.Discharge_Date__c                         =     discharge.Discharge_Date__c; // It will put the updated value here
                newDischarge.Discharge_Location_Type__c             =    discharge.Discharge_Location_Type__c;
                newDischarge.Discharge_Location__c                     =    discharge.Discharge_Location__c ;
                newDischarge.Facility_ID__c                         =     discharge.Facility_ID__c;
                newDischarge.Facility_Name__c                         =     discharge.Facility_Name__c;
                newDischarge.name                                     =     discharge.name;
                newDischarge.State__c                                 =     discharge.State__c;
                newDischarge.Status_Code_ID__c                         =     discharge.Status_Code_ID__c;
                newDischarge.Zip__c                                 =     discharge.Zip__c;
                newDischarge.Progress_Notes__c                         =     discharge.Progress_Notes__c;
                newDischarge.Medicaid_ID__c                         =     discharge.Medicaid_ID__c;
                newDischarge.Medicare_ID__c                         =     discharge.Medicare_ID__c;
                newDischarge.Other_Diagnosis_ICD_Codes__c             =    discharge.Other_Diagnosis_ICD_Codes__c;
                newDischarge.Other_Diagnosis_ICD_Descriptions__c     =     discharge.Other_Diagnosis_ICD_Descriptions__c;
                newDischarge.Patient_ID_PCC__c                         =     discharge.Patient_ID_PCC__c;
                newDischarge.Primary_Diagnosis_ICD_Code__c             =    discharge.Primary_Diagnosis_ICD_Code__c;
                newDischarge.Primary_Diagnosis_ICD_Description__c     =    discharge.Primary_Diagnosis_ICD_Description__c;
                
                newDischargeList.add(newDischarge); // Preparing the list for DML operation
            }//IF ENDS
            
        }// FOR ENDS
        
        try {
            // check to see if the list is empty before performing the DML operation
            if(!newDischargeList.isEmpty()) {
                insert newDischargeList;
            }
        }catch(DMLException e) {
            System.debug('Unable to insert the Account record : ' + e.getMessage());
        }
    }
}


I believe this time you will be all set.


 
PRAKASH JADA 13PRAKASH JADA 13
Thank you for your patience.
Michael MMichael M
I don't know why but it's still not working for me. I copied the code exactly as you wrote it. The updates are updating the old record, and 2 new records are getting created. Sorry for all the back and forth. 
PRAKASH JADA 13PRAKASH JADA 13
No issues Michael,
1. Append your name to the last name in the code and save it.
2. Please enable the debug logs for you in the environment that you are testing.
3. Create a new record with the discharge date manually and edit that record and change the discharge date to discharge date + 5 days. 
4. Now go and verify the 2 records that were creating.  It would
5. Go to the debug logs to open the apex log that created for this transaction and copy the statements from system.debug and do a search. The statement should appear only one time. If it is occurring more than once then you need to do a search in (developer console --> edit --> search in all files --> past the object api name) object if there are any DML statements. that will help you to understand more.

Hope this helps. 
Michael MMichael M
Hi Prakash,
I added a Trigger Handler class to prevent it from creating 2 new records, and this seems to be working.
Here is what it looks like:
CLASS:
public class RecursiveTriggerHandler{
     public static Boolean isFirstTime = true;
}

TRIGGER:
trigger DischargeTrigger2 on Discharge__c (after update) {
   if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;
    // After event
    if(Trigger.isAfter) {
        if(Trigger.isUpdate) {
             DischargeHandler.onAfterSave(Trigger.New, Trigger.oldMap);
        }
    }
}
}


However, the other problem is still there. I am creating a new record manually, with e.g. Name= 'Old', DischargeDate = 2/1/2020. I save it. Then I change the name to 'New' and the DischargeDate to 2/15/20. The record saves and updates, and a new record is created with the same information. I need to prevent the record from updating itself. I don't see where in the code this is being prevented... all the code is doing is inserting the new record with the same information. But the trigger is "After update" so by definition the updates are already taking effect in the old record... Right? What am I missing here- where is the code telling it not to accept the updates for the original ('Old') record?
PRAKASH JADA 13PRAKASH JADA 13
You are doing the update manually here but if it goes to production the when a third party tries to update the record with the above satisfactory condition then the system will automatically create the new record for you. Here are you are manually inserting a record and updating it manually so that is why the values are getting updated. 
Michael MMichael M
I just did the update from the thirty party app, but again the same thing happened. A new record was created, but the old record also received all of the same updates...

I still don't see where in the code we are telling it not to update the old record. 
PRAKASH JADA 13PRAKASH JADA 13
Hey, the above will work after the update but if you want to keep the values from the insert and if you want to create the new record when the date difference is 5 days then use the below code.

Trigger:
-------------------
trigger DischargeTrigger on Discharge__c (before update) {
    // After event
    if(Trigger.isBefore) {
        if(Trigger.isUpdate) {
            DischargeHandler.onAfterSave(Trigger.New, Trigger.oldMap);
        }
    }
}


Apex class:
----------------------
public with sharing class DischargeHandler {
    // Trigger handler Method to call from the Trigger
    public static void onAfterSave(List<Discharge__c> dischargeList, Map<Id, Discharge__c> oldDischargeMap) {
        System.debug('Discharge List : ' + dischargeList.size());
        
        List<Discharge__c> newDischargeList = new List<Discharge__c>(); // List to perform the DML operation
        Integer dateDiff;
        // Loop to Iterate over the records that were updated
        for(Discharge__c discharge : dischargeList) {
            dateDiff = oldDischargeMap.get(discharge.Id).Discharge_Date__c.daysBetween(discharge.Discharge_Date__c); // To calculate the days
            System.debug('Date difference : ' +dateDiff);
            
            // Condition to check for the days count
            if( dateDiff > 5 ) {
                Discharge__c newDischarge                                 =     new Discharge__c();
                
                // Assign all the field over here
                newDischarge.Address__c                                 =    discharge.Address__c;
                newDischarge.City__c                                     =    discharge.City__c;
                newDischarge.Date_of_Birth__c                             =    discharge.Date_of_Birth__c;
                newDischarge.Discharge_Date__c                             =    discharge.Discharge_Date__c; // It will put the updated value here
                newDischarge.Discharge_Location_Type__c                 =    discharge.Discharge_Location_Type__c;
                newDischarge.Discharge_Location__c                         =    discharge.Discharge_Location__c ;
                newDischarge.Facility_ID__c                             =    discharge.Facility_ID__c;
                newDischarge.Facility_Name__c                             =    discharge.Facility_Name__c;
                newDischarge.name                                         =    discharge.name;
                newDischarge.State__c                                     =    discharge.State__c;
                newDischarge.Status_Code_ID__c                             =    discharge.Status_Code_ID__c;
                newDischarge.Zip__c                                     =    discharge.Zip__c;
                newDischarge.Progress_Notes__c                             =    discharge.Progress_Notes__c;
                newDischarge.Medicaid_ID__c                             =    discharge.Medicaid_ID__c;
                newDischarge.Medicare_ID__c                             =    discharge.Medicare_ID__c;
                newDischarge.Other_Diagnosis_ICD_Codes__c                 =    discharge.Other_Diagnosis_ICD_Codes__c;
                newDischarge.Other_Diagnosis_ICD_Descriptions__c         =    discharge.Other_Diagnosis_ICD_Descriptions__c;
                newDischarge.Patient_ID_PCC__c                             =    discharge.Patient_ID_PCC__c;
                newDischarge.Primary_Diagnosis_ICD_Code__c                 =    discharge.Primary_Diagnosis_ICD_Code__c;
                newDischarge.Primary_Diagnosis_ICD_Description__c         =    discharge.Primary_Diagnosis_ICD_Description__c;
            }//IF ENDS
            
        }// FOR ENDS
        
        // Loop to iterate over the List of updating records
        for(Discharge__c discharge : dischargeList) {
            dateDiff = oldDischargeMap.get(discharge.Id).Discharge_Date__c.daysBetween(discharge.Discharge_Date__c); // To calculate the days
            System.debug('Date difference : ' +dateDiff);
            
            // Condition to check for the days count
            if( dateDiff > 5 ) {
                // Assigning the values from Insert scenario
                discharge.Address__c                                 =     oldDischargeMap.get(discharge.Id).Address__c;
                discharge.City__c                                     =     oldDischargeMap.get(discharge.Id).City__c;
                discharge.Date_of_Birth__c                            =     oldDischargeMap.get(discharge.Id).Date_of_Birth__c;
                discharge.Discharge_Date__c                         =     oldDischargeMap.get(discharge.Id).Discharge_Date__c; 
                discharge.Discharge_Location_Type__c                 =    oldDischargeMap.get(discharge.Id).Discharge_Location_Type__c;
                discharge.Discharge_Location__c                     =     oldDischargeMap.get(discharge.Id).Discharge_Location__c ;
                discharge.Facility_ID__c                             =     oldDischargeMap.get(discharge.Id).Facility_ID__c;
                discharge.Facility_Name__c                             =     oldDischargeMap.get(discharge.Id).Facility_Name__c;
                discharge.name                                         =     oldDischargeMap.get(discharge.Id).name;
                discharge.State__c                                     =     oldDischargeMap.get(discharge.Id).State__c;
                discharge.Status_Code_ID__c                         =     oldDischargeMap.get(discharge.Id).Status_Code_ID__c;
                discharge.Zip__c                                     =     oldDischargeMap.get(discharge.Id).Zip__c;
                discharge.Progress_Notes__c                         =     oldDischargeMap.get(discharge.Id).Progress_Notes__c;
                discharge.Medicaid_ID__c                             =     oldDischargeMap.get(discharge.Id).Medicaid_ID__c;
                discharge.Medicare_ID__c                             =     oldDischargeMap.get(discharge.Id).Medicare_ID__c;
                discharge.Other_Diagnosis_ICD_Codes__c                 =     oldDischargeMap.get(discharge.Id).Other_Diagnosis_ICD_Codes__c;
                discharge.Other_Diagnosis_ICD_Descriptions__c         =     oldDischargeMap.get(discharge.Id).Other_Diagnosis_ICD_Descriptions__c;
                discharge.Patient_ID_PCC__c                         =     oldDischargeMap.get(discharge.Id).Patient_ID_PCC__c;
                discharge.Primary_Diagnosis_ICD_Code__c             =     oldDischargeMap.get(discharge.Id).Primary_Diagnosis_ICD_Code__c;
                discharge.Primary_Diagnosis_ICD_Description__c         =     oldDischargeMap.get(discharge.Id).Primary_Diagnosis_ICD_Description__c;
            }
        }
        try {
            // check to see if the list is empty before performing the DML operation
            if(!newDischargeList.isEmpty()) {
                insert newDischargeList;
            }
        }catch(DMLException e) {
            System.debug('Unable to insert the Account record : ' + e.getMessage());
        }
    }
}


This is working for me.

What it will do.

Create a new record
Name = Prakash
Discharge Date = today
Save the record

Update the same record and change the discharge from today to today + 5
then 

Update record will save with 
Name = Prakash
Discharge Date = today

Create a new record
Name = Prakash
Discharge Date = today + 5


This is the test performed. If this is the same case then you can use the above code.


Thanks,
This was selected as the best answer
Michael MMichael M
Hi Prakash, I just tried this (both manually, and through the execute anonymous window), and received the following error: 

"System.DmlException: Update failed. First exception on row 0 with id a0N2g000000JrnyEAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, DischargeTrigger2: execution of AfterUpdate caused by: System.FinalException: Record is read-only Class.DischargeHandler.onAfterSave: line 53, column 1 Trigger.DischargeTrigger2: line 7, column 1: []"

Line 7 column1 on the trigger is:  DischargeHandler.onAfterSave(Trigger.New, Trigger.oldMap);
Line 53 column 1 on the class is: discharge.Address__c      =     oldDischargeMap.get(discharge.Id).Address__c;

 
PRAKASH JADA 13PRAKASH JADA 13
I changed the trigger logic as well. Did you update the trigger as well? 
PRAKASH JADA 13PRAKASH JADA 13
the trigger event is before update
 
Michael MMichael M
You're right- I had forgot to update the trigger. However, I tried with the new trigger, and I did not get an error, however nothing happened. A new record was not created, and all updates were applied to the old record. 
PRAKASH JADA 13PRAKASH JADA 13
Create a new record
Name = Prakash
Discharge Date = today
Save the record

Update the same record and change the discharge from today to today + 5
then 

Update record will save with 
Name = Prakash
Discharge Date = today

Create a new record
Name = Prakash
Discharge Date = today + 5


Do this step and check for the results it is working for me.
Michael MMichael M
It's still not working. I'm not sure why not... 
PRAKASH JADA 13PRAKASH JADA 13
Hey Michael,


Sorry about the back and forth.

1. Did the code save perfectly? without any issues?
2. The trigger event is "Before update", if condition should be Trigger.isBefore and second if condition should be Trigger.isUpdate?
3. The calling method from the trigger is equal to the called method in the Handler that is onAfterSave?
4. Are you sure that you are creating and updating the record in way I mentioned? (In my example I said today +5 meaning please do not test with exactly 5 days from now please add days more than 5 that what you are expecting).
5. Enable the debug log for you. Create a record and update the record as I mentioned above. open the debug log and do ctrl+f and paste the below lines by removing the double quotes
"Discharge List:  " Result should be 1
"Date difference: "Result should be 6 or above
it should not equal to 5 because you are strictly checking for more than 5 days.

6. Let me know if the above 5 are good.

 
Michael MMichael M
No worries- I appreciate your help!
1. Yes, it saved just as it would normally without any trigger. 
2. No - I forgot this step, my apologies.  I did this and it works! Thank you so much for all your patience. I will mark as best answer. 
PRAKASH JADA 13PRAKASH JADA 13
Thank you so much, Michael, for confirming that it is working.  Please rewrite the comments. check for nulls. Change the method name from onAfterSave to onBeforeUpdate it would be appropriate.

Thank you so much for your patience. Much appreciated. 

Have a great rest of your day.
Michael MMichael M
Hi Prakash, can I ask you another related question, if you don't mind. 
We also have a "before insert" trigger on Discharge object, and we need that if a user inserts a new Record where that name already exists, we want to run the whole before discharge operation discussed above. I wrote this trigger:

trigger DischargeTrigger on Discharge__c (before insert) {
Set<String> newNameSet   = new Set<String>();

for (Discharge__c disch : trigger.new){
   if (disch.Name != null && disch.Other_Diagnosis_ICD_Descriptions__c !=null ){
            newNameSet.add(disch.name);
        }
        Discharge__c oldDis = [SELECT Id, name, Discharge_Date__c FROM Discharge__c WHERE name =:newNameSet];
Integer dateDiff;
Integer datedif;     
            dateDiff = disch.Discharge_Date__c.daysBetween(oldDis.Discharge_Date__c); // To calculate the days
            dateDif = oldDis.Discharge_Date__c.daysBetween(disch.Discharge_Date__c);
        if( dateDiff > 5 || dateDif > 5) {
        oldDis.Discharge_Date__c = disch.Discharge_Date__c;
        update oldDis;
        }
    }    
}

I am adding a new record with a name which already exists, but yet am getting this error: "System.QueryException: List has no rows for assignment to SObject". What should I do about it?

Should I open up a new case?
PRAKASH JADA 13PRAKASH JADA 13
Hey Michael before inserting the record means the record is not committed to the database 
PRAKASH JADA 13PRAKASH JADA 13
SELECT Id, name, Discharge_Date__c FROM Discharge__c WHERE name =:newNameSet this query will cause the issue
 
Michael MMichael M
Ok, great, thank you Prakash.
PRAKASH JADA 13PRAKASH JADA 13
so your question is when the user inserts a new record and that record already existing database then you want to assign the values from that record to this one right?
PRAKASH JADA 13PRAKASH JADA 13
if that is the case use trigger event like onAfterInsert and if the matching name is found use the dml update to update that record. if no don't do anything in this way you can do it.
Michael MMichael M
So in theory this should work right:

trigger DischargeTrigger3 on Discharge__c (after insert) {

    Set<String> newNameSet   = new Set<String>();
    if (trigger.isafter){
for (Discharge__c disch : trigger.new){
   if (disch.Name != null ){
            newNameSet.add(disch.name);
        }
        Discharge__c oldDis = [SELECT Id, name, Discharge_Date__c FROM Discharge__c WHERE name =:newNameSet order by createddate desc limit 1];
Integer dateDiff;
Integer datedif;     
            dateDiff = disch.Discharge_Date__c.daysBetween(oldDis.Discharge_Date__c); // To calculate the days
            dateDif = oldDis.Discharge_Date__c.daysBetween(disch.Discharge_Date__c);
        if( dateDiff > 5 || dateDif > 5) {
        oldDis.Discharge_Date__c = disch.Discharge_Date__c;

        update oldDis;
                delete disch;
        }
    }    
    }
}

However, when I add a new record with the same name as the old one, the new record is not getting deleted and nothing really is happening. 
PRAKASH JADA 13PRAKASH JADA 13
trigger DischargeTrigger3 on Discharge__c (after insert, after update) {
    
    Set<String> newNameSet   = new Set<String>();
    Set<DateTime> createDateSet = new Set<DateTime>();
    if (trigger.isafter){
        if(Trigger.isInsert) {
            for (Discharge__c disch : trigger.new){
                if (disch.Name != null ){
                    newNameSet.add(disch.name);
                    createDateSet.add(disch.CreatedDate);

                }
                Discharge__c oldDis = [SELECT Id, name, Discharge_Date__c 
                                       FROM Discharge__c 
                                       WHERE name =:newNameSet AND 
                                       CreatedDate != :createDateSet 
                                       order by createddate desc limit 1];

                Integer dateDiff;
                Integer datedif;     
                dateDiff = disch.Discharge_Date__c.daysBetween(oldDis.Discharge_Date__c); // To calculate the days
                datedif = oldDis.Discharge_Date__c.daysBetween(disch.Discharge_Date__c);

                if( dateDiff > 5 || datedif > 5) {
                    oldDis.Discharge_Date__c = disch.Discharge_Date__c;
                    
                    update oldDis;
                    //delete disch;
                }
            }    
        }
        
        if(trigger.isUpdate) {
            Set<String> newNameSet   = new Set<String>();
            for(Discharge__c discharege : Trigger.New) {
                if (discharege.Name != null ){
                    newNameSet.add(discharege.name);
                }
                Discharge__c oldDis = [SELECT Id, name, Discharge_Date__c 
                                       FROM Discharge__c 
                                       WHERE name =:newNameSet
                                       order by createddate desc limit 1];
                delete oldDis;
            }
        }
    }
    
    
    
}


1. The reason for not working because you have a filter saying created date desc and that will bring the same record so the data difference is 0.   So I added one more set to take the created date and changed the query as well in the where clause so it will update the old record.
2. for delete you can not delete the records on after insert because they fall under trigger.new so salesforce limitation on trigger.new and trigger.old variables. so I used on after update logically here a new record is the old one that we are updating so we can delete the new one. 


Try it and let me know if it is working for you. It is working for me.
Michael MMichael M
OK, so here is the error I am getting when I try to add a new of a record that already exists, with this code:

DischargeTrigger3: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id a0N2g000000JrkwEAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, DischargeTrigger2: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object Class.DischargeHandler.onBeforeUpdate: line 46, column 1 Trigger.DischargeTrigger2: line 7, column 1: [] Trigger.DischargeTrigger3: line 27, column 1
Michael MMichael M
Hey -- I think I will go about this a different way. Instead of  a new trigger, I am think to just add a new window with a couple fields (including discharge date), where they can update the date. This will trigger the old workflow, and may simplify things. 
PRAKASH JADA 13PRAKASH JADA 13
yes you can try it.
PRAKASH JADA 13PRAKASH JADA 13
Initial Logic: When the 3rd party sends the Update with discharge date greater than 5 days then you are creating a new one and updating the old one.
New Logic. If a user creates a new record you are again updating the old one and deleting the new one.

If this needs to work with code.


you need to create a new field with Import action.
Create, Update as values if it hard to give it to the third party then you can default the value to Insert as a picklist field. Create a flag and check it after insert if that flag is true then you know it is updated. On Update, you can reverse back the old values and you can create a new one with import action as a Create. So that it won't delete the record with update action which is set to the 3rd party record.  Now if the user is creating a new record that will fall under the import action Insert so you can compare the records based on discharge data and import action from there you can decide whether you can delete or update the records based on your requirement. This is just an idea. 
Michael MMichael M
The flow seems to do the job. Thanks so much for all your help.