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
Tommy GeorgiouTommy Georgiou 

Field update from a 2nd line item

Hello,

I have created a custom object called Reservaitons. I am looking for a way to update a field as soon as I receive a second reservation(2nd line item).

I tried a workflow rule but on the criteria I couldn't find anything that is about a second line item. My unique field is ReservationID but the client might already have a reservation on his card. 
Best Answer chosen by Tommy Georgiou
StephenKennyStephenKenny
Hi Tommy, try this:
trigger ReservationTrigger on Reservations__c (after insert) {
    // After Insert, if the Status is confirmed update the Contact
    Set<Id> contactIds = new Set<Id>();
    for(Reservations__c oneReservation:trigger.new()){
        if(oneReservation.ReservationStatus__c == 'Confirmed'){
            contactIds.add(oneReservation.Id);
        }
    }
    // Get a list of matching contacts  
    List<Contact> existingContacts = [Select Id, Repeater__c,
                                        (Select id from Reservations__r)  
                                        From Contact 
                                        Where Id in:contactIds
                                        And Repeater__c = 'False'];

    // Itterate through the contacts
    List<Contact >contactsToUpdate = new List<Contact>();
    if(existingContacts.size()>0){
        for(Contact oneContact: existingContacts){
            // Check if the Contact has two Reservations, we only want to update on the secon
            List<Reservations__c> existingReservations = oneContact.getSObjects('Reservations__r');
            if(existingReservations.size() == 2){
                oneContact.Repeater__c = True;
                contactsToUpdate.add(oneContact);
            }
        }
        // Update the contacts
        Update contactsToUpdate;
    }
}

 

All Answers

StephenKennyStephenKenny
Hi Tommy,

Could you provide a little more information on the use case: Are you saying that you want to update a field on another seperate record or are you daying you want to update the picklist value when a reservation record is created?

For the first point above (updating a seperate record), you would have to use a trigger to achieve this, but for the second point (updating the picklist on the created record) you can do this via workflow. If you can provide more context then we can get to the answer for you.

Please remember to mark this thread as solved with the answer that best helps you.

Regards
Stephen 
Tommy GeorgiouTommy Georgiou
Hi Stephen,


Sorry for not providing for info on my problem. My custom object has a master detail relationship with Contacts. The field that I want to update is a custom check box field on Contacts. 
Regarding your question yes I want to update the field when a 2nd record is created. But the hint is on the record there is a status field. So when the 2nd record's status is confirmed then the check box becomes true
StephenKennyStephenKenny
Hi Tommy,

Not a problem - have you investigated using a roll up summary field on the Contact to get this information? This may provide you with the same or a similar answer to what you are looking for.

Alternatively, if you must update a checkbox, then you will require a trigger to do this. The trigger would be on the Reservation object and would be after insert (if I understand the requiremnet). Are you familier with writing triggers or do you need help with this?

Regards
Stephen
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Thank you for your help. I think a roll up sum will make the work with a workflow afterwards.
Not so familiar with tiggers writing :(

Since you know can I ask you one more thing that might need a trigger?
Tommy GeorgiouTommy Georgiou
I have created a rollup field that counts the records. Then I created a workflow rule where rollupfield>1 and then a field update to true on my checkbox and still won't get the box checked. Ofcourse the workflow is activated

User-added image
StephenKennyStephenKenny
Hi Tommy,

It can take some time for rollup summary fields to calculate. Can you confirm that the rollup summary field contains the correct data? Secondly, the workflow rule will only fire when the contact record is updated. It wont automatically fire unfortunatly.

Perhaps you could change your existng check box to field be a fomula field that displays True if your rollup summary field is greater than 1?
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Yes it does contains the correct data. I have edited and saved the page a couple of times to see id this works actually, but still nothing happened. 

Will wait a bit more and then try the formula field.

 
StephenKennyStephenKenny
Hmm perhaps the workflwo field is not being executed. In any case, I am not sure the workflow rule is the best approach as the field will only be updated if someobody first updates the contact (to kickoff the workflow rule). This will not be very effective for reporting purposes. I would recommend the formula field approach as this does not require any interaction from the user - the field will always contain the correct value.
Tommy GeorgiouTommy Georgiou
But what happens when I want two rules for it. If you have seen my screenshot I have a Reservation Status. So my next step will be when the rollupfield is > 1 and the reservation status is confirmed then the checkbox becomes true. Any ideas for it? Maybe a trigger?
StephenKennyStephenKenny
Ah yes, the formula field is quite specific to one use case but if you want to add in additional logic and/ or rules then a trigger would be the way to go. Let me know if you need any help writing it. The trigger itself should be pretty straught forward, however, the thing to bear in mind is how often do you want to update the contact record.

For example, when the first reservation is created, I suspect you would want to update the checkbox and the status + what ever other fields are needed. But what about when the 5th & 6th reservation is created against the same contact - do you still need the trigger to run and update the fields - or do you only care about the first reservation.

Its always the best approach to think through the full requiremnet before you start writing code - my recomendation is to start small and work your way up from there.
Tommy GeorgiouTommy Georgiou
Hi Stephen,

I will indeed need some help with the trigger. What I want is when the second reservation comes in and the staus is confirmed to check that box once and remain checked. I do not care for the rest that will come in the future. To give you a hind of my business, is when a second resrvation comes in and it's confirmed(received the payment) that means that client(contact) is now a repeater client. That is why I do want this for the second confirmed reservation and not care about the future ones.
 
StephenKennyStephenKenny
Ok, try this
trigger ReservationTrigger on Reservation__c (after insert) {
	// After Insert, if the Status is confirmed update the Contact
	Set<Id> contactIds = new Set<Id>();
	for(Reservation__c oneReservation:trigger.new()){
		if(oneReservation.Status__c == 'Confirmed'){
			contactIds.put(reservation.Contact__c);
		}
	}
	// Get a list of matching contacts  
	List<Contact> contactsToUpdate = [Select Id, CheckboxField__c 
										From Contact 
										Where Id in:contactIds
										And CheckboxField__c == False];

	// Itterate through the contacts and assign new values
	if(contactsToUpdate.size()>0){
		for(Contact oneContact: contactsToUpdate){
			oneContact.CheckboxField__c = True;
		}
		// Update the contacts
		Update contactsToUpdate
	}
}
I have made some assumptions regarding the object and field api names so you will have to check these.

The code above will run whenever a reservation is created.
- If the status is 'confirmed', the code will get the parent contact if the checkbox field is false, and update it to true.
- if the contact already has this checkbox ticke, it will not do anything


 
Tommy GeorgiouTommy Georgiou
Hi Stephen,


Thanx for the code. Does the trigger works for the 2nd reservation or the first? Because what i want it to work work is for the second reservation
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Will try your trigger and try to implement the res status as well
StephenKennyStephenKenny
Hi Tommy,

The trigger will fire on all Reservations once they are created - the first, 2nd, 3rd etc... However, the contact will only be updated if both of the following is true:
- The reservation status = 'Confirmed'
- The checkbox field on the contact is false

 
Tommy GeorgiouTommy Georgiou
Hi Stephen,

The problem is that I want this to fire only on the 2nd reservation. On the first the client does not become a repeater
 
StephenKennyStephenKenny
HI Tommy,

Ok, I have modified the code below so the contact will only be updated if they have two reservation records - if they have 1 or 3 or 300, nothing will happen which I think is what you want? Remember to double check the field and object names below as I am just guessing.
 
trigger ReservationTrigger on Reservation__c (after insert) {
	// After Insert, if the Status is confirmed update the Contact
	Set<Id> contactIds = new Set<Id>();
	for(Reservation__c oneReservation:trigger.new()){
		if(oneReservation.Status__c == 'Confirmed'){
			contactIds.put(reservation.Contact__c);
		}
	}
	// Get a list of matching contacts  
	List<Contact> existingContacts = [Select Id, CheckboxField__c,
										(Select id from Reservations__r)  
										From Contact 
										Where Id in:contactIds
										And CheckboxField__c == False];

	// Itterate through the contacts
	List<Contact >contactsToUpdate = new List<Contact>();
	if(existingContacts.size()>0){
		for(Contact oneContact: existingContacts){
			// Check if the Contact has two Reservations, we only want to update on the secon
			List<Reservation__c> existingReservations = oneContact.getSObjects('Reservations__r');
			if(existingReservations.size() == 2){
				c.CheckboxField__c = True;
				contactsToUpdate.add(c);
			}
		}
		// Update the contacts
		Update contactsToUpdate;
	}
}

 
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Thank you very much
Few questions on the trigger. What is reservation.Contact__c?And what is Reservations_r?

I am sking becaus e when I put my own api's it says that reservation.contact__c does not exists


 
StephenKennyStephenKenny
Hi Tommy,

Appologies, the code above should read 'oneReservation.Contact__c' where Contact__c is the name of the contact field on the Reservation object. I am taking a guess at the name here so if you have named this field somehting different, you will need to chnage the code to reflect this.

Reservations_r is the child relationship name of your Contact field on the reservation object. Again, I am taking a guess as to what this is called so if you have named it something different, you will have to update the code to reflect this.

Please remember to mark this thread as solved so that others may find this thread more easily.

Regards
Stephen 
Tommy GeorgiouTommy Georgiou
Hi Stephen,

First of all I want to thank you for your patience and apologise for my lack of knowledge on triggers.

I have proceeded to the changes you suggest and I get an error on line 23 

[Error] Error: Compile Error: Variable does not exist: c.Repeater__c at line 23 column 17
StephenKennyStephenKenny
Hi Tommy,

Not a problem - happy to help. I have noticed an error in the code I gave you. On line 23 & 24, replace 'c' with 'oneContact'.
Tommy GeorgiouTommy Georgiou
Hi Stephen
Please review the code below
trigger ReservationTrigger on Reservations__c (after insert) {
    // After Insert, if the Status is confirmed update the Contact
    Set<Id> contactIds = new Set<Id>();
    for(Reservations__c oneReservation:trigger.new()){
        if(oneReservation.ReservationStatus__c == 'Confirmed'){
            contactIds.put(oneReservation.Email__c);
        }
    }
    // Get a list of matching contacts  
    List<Contact> existingContacts = [Select Id, Repeater__c,
                                        (Select id from Reservations__r)  
                                        From Contact 
                                        Where Id in:contactIds
                                        And Repeater__c = 'False'];

    // Itterate through the contacts
    List<Contact >contactsToUpdate = new List<Contact>();
    if(existingContacts.size()>0){
        for(Contact oneContact: existingContacts){
            // Check if the Contact has two Reservations, we only want to update on the secon
            List<Reservations__c> existingReservations = oneContact.getSObjects('Reservations__r');
            if(existingReservations.size() == 2){
                oneContact.Repeater__c = True;
                contactsToUpdate.add(c);
            }
        }
        // Update the contacts
        Update contactsToUpdate;
    }
}

[Error] Error: Compile Error: Variable does not exist: c at line 24 column 38

If I delete c i Get the following error

Error: Compile Error: Method does not exist or incorrect signature: [Set<Id>].put(Id) at line 6 column 13

 
StephenKennyStephenKenny
Hi Tommy, try this:
trigger ReservationTrigger on Reservations__c (after insert) {
    // After Insert, if the Status is confirmed update the Contact
    Set<Id> contactIds = new Set<Id>();
    for(Reservations__c oneReservation:trigger.new()){
        if(oneReservation.ReservationStatus__c == 'Confirmed'){
            contactIds.add(oneReservation.Id);
        }
    }
    // Get a list of matching contacts  
    List<Contact> existingContacts = [Select Id, Repeater__c,
                                        (Select id from Reservations__r)  
                                        From Contact 
                                        Where Id in:contactIds
                                        And Repeater__c = 'False'];

    // Itterate through the contacts
    List<Contact >contactsToUpdate = new List<Contact>();
    if(existingContacts.size()>0){
        for(Contact oneContact: existingContacts){
            // Check if the Contact has two Reservations, we only want to update on the secon
            List<Reservations__c> existingReservations = oneContact.getSObjects('Reservations__r');
            if(existingReservations.size() == 2){
                oneContact.Repeater__c = True;
                contactsToUpdate.add(oneContact);
            }
        }
        // Update the contacts
        Update contactsToUpdate;
    }
}

 
This was selected as the best answer
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Tried but getting error like Error: Compile Error: Variable does not exist: trigger at line 4 column 40

 
StephenKennyStephenKenny
Hi Tommy,

Did you copy and past the code fom above? There is no variable on line 4 so the error message does not make sense. Can you try again and if there is an error message, please copy and paste it.

Cheers
 
Tommy GeorgiouTommy Georgiou
trigger ReservationTrigger on Reservations__c (after insert) {
    // After Insert, if the Status is confirmed update the Contact
    Set<Id> contactIds = new Set<Id>();
    for(Reservations__c oneReservation:trigger.new()){
        if(oneReservation.ReservationStatus__c == 'Confirmed'){
            contactIds.add(oneReservation.Id);
        }
    }
    // Get a list of matching contacts  
    List<Contact> existingContacts = [Select Id, Repeater__c,
                                        (Select id from Reservations__r)  
                                        From Contact 
                                        Where Id in:contactIds
                                        And Repeater__c = 'False'];

    // Itterate through the contacts
    List<Contact >contactsToUpdate = new List<Contact>();
    if(existingContacts.size()>0){
        for(Contact oneContact: existingContacts){
            // Check if the Contact has two Reservations, we only want to update on the secon
            List<Reservations__c> existingReservations = oneContact.getSObjects('Reservations__r');
            if(existingReservations.size() == 2){
                oneContact.Repeater__c = True;
                contactsToUpdate.add(oneContact);
            }
        }
        // Update the contacts
        Update contactsToUpdate;
    }
}

Tried again and the error is [Error] Error: Compile Error: Variable does not exist: trigger at line 4 column 40

User-added image
StephenKennyStephenKenny
Oh, of course, my mistake - please remove the two brackets after 'trigger.new'.
So line 4 should be :for(Reservations__c oneReservation:trigger.new){
Tommy GeorgiouTommy Georgiou
Hi Stephen,

I guess I am driving you crazy.

Next error that I cannot understand is Error: Compile Error: value of filter criterion for field 'Repeater__c' must be of type boolean and should not be enclosed in quotes at line 10 column 38

Repeater is a checkbox field! I quoting it and next error is

Error: Compile Error: unexpected token: 'Repeater__c' at line 10 column 49

 
StephenKennyStephenKenny
Hi Tommy, not a problem! Hopeffuly a good learning experience for you.
Boolean values should not be in quotes so chnage line 14 to this: And Repeater__c = False];
Tommy GeorgiouTommy Georgiou
Ok!!! It's saved now!!

Do I need to deployed it onto production to see if it works? Or I can see it through the sandbox?
StephenKennyStephenKenny
Great, you will be able to see this in action in the sandbox. Use the sandbox to test that everything works as you would expect it to.

Got there in the end!
Tommy GeorgiouTommy Georgiou
Hi Stephen,

I actually trying to see if it works but It doesn't seem to get the checkbox to true!! 
StephenKennyStephenKenny
HI Tommy,

You will have to work through the testing yourself as it will be quite hard to guide you without being able to see it but if you do run into issues feel free to ask away.

The code above should fire everytime you insert a reservation - it will not fire when a reservaion is updated.
If at the point of insert, the reservation has a status of 'Confirmed', and the reservation in question happens to be the second one (not the 3rd or 4th etc), then the contact field should be updated.

if the contact is not updated, try the following:
- If you already have the contact open on a seperate tab, refresh your browser to see the update.
Perhaps the logic needs to be adjusted in the code, does the status equal 'Confirmed', please note this is case sensitive.
Tommy GeorgiouTommy Georgiou
Hi Stephen,

Indeed I need to test it a few times to see if it works. Thank you very much for your help and the lesson on triggers!! Thanks again
StephenKennyStephenKenny
Not a problem Tommy - please remember to mark this thread as solved so that others may find this thread more easily.

Regards,
Stephen 
Tommy GeorgiouTommy Georgiou
Hi Stephen,


I have a problem that came up with this. In case of the reservation id. Sometimes when the client updates his reservation rhe ResId remains the same but the resdetailid changes. So what happens is that on the related list on the contact's card the reservation appears 5 times lets say but its still one res. Is there a way to implement this on the trigger?

And another question. To transfer it to the production I would need a test class correct? 
StephenKennyStephenKenny
Hi Tommy,

I dont really understand the first point - if 5 reservations appear, then these are 5 individual records and the trigger above will fire on each, however will only try to update the contact record on the second reservation record.

Regarding production, yes you will require a test method for the trigger above as well as any other code you are looking to move into prooduction.

Regards
Stephen
Tommy GeorgiouTommy Georgiou
Hi Stephen. 

Yes indeed there are 5 records but they all have the same reservationid. the only different in those records is if the client has tried to update / change something the reservationdetailid changes but the reservationid remains the same.

Do you happen to know any good books for a begginer like mew to get a better knowledge for apex ttiggers classes etc?
StephenKennyStephenKenny
Absoloutley, the apex workbook has a bunch of tutorials to get you started:
https://developer.salesforce.com/docs/atlas.en-us.apex_workbook.meta/apex_workbook/

There are also a bunch of other resources available here, all with tutorials and examples:
https://developer.salesforce.com/docs?filter_text=&service=Force.com&select_type=&version=33.0&lang=en-us&sort=title (https://developer.salesforce.com/docs?filter_text=&service=Force.com&select_type=&version=33.0⟨=en-us&sort=title)