0

I have a custom object named "Property Booking" where if the status changed to approved I have to create a record for my "Quotation" custom object. The tricky part here for me is I don't know how I can input values using the child to parent.

"Property"(master) and "Customer"(master) have a master-detail relationship with my "Property Booking"(detail) object

I tried using the following: pb.Property__r.Type -> not working. Error: Variable does not exist: Type ( but it does exist in the object) pb.Customer__r.Email -> not working.

newQuoList.Property_Type__c = ; ---- what I am trying to do with the line of code above is to insert a "Type" that is based on the "Property" parent field

newQuoList.Customer_Email__c = ; ---- what I am trying to do with the line of code above is to insert an "Email" that is based on the "Customer" parent field.

hoping to have some help or shed some light for this concept. I am quite new here, I am told that I should query in order to get it. But I have no idea on how to start on this.

These are my codes:

public static void isAfterUpdate(List<Property_Booking__c> pbList){
              for(Property_Booking__c pb: pbList){
                try{
                    //if the status moves to approved, then a new quotation record should be created, all the fields
                    //of the quotation record should take in data from rest of the 3 objects except quoted to customer. 
                    //Price should be the quoted price - Case # 8
                    if(pb.Status__c == 'Approved'){
                        //list of quotation record to be created
                        List<Quotation__c> quoList = new List<Quotation__c>();
                        try{
                            //insert quotation records
                            for(Quotation__c newQuoList: quoList){
                                newQuoList.Booking_Ref__c = pb.Name;
                                newQuoList.Property_Name__c = pb.propertyName__c;                        
                                newQuoList.Property_Type__c = ;
                                newQuoList.Customer_Name__c = pb.customerName__c;
                                newQuoList.Acquire_Property_By__c = pb.Acquire_Property_By__c;
                                newQuoList.Price__c = pb.Quoted_Price__c;
                                newQuoList.Customer_Email__c = ;
                                quoList.add(newQuoList);
                            }
                            insert quoList;
                        }catch(DmlException e){
                            System.debug('An unexpected error has occured: ' +e.getMessage());
                        }
                    }
}

My trigger

trigger PropertyBookingTriggers on Property_Booking__c (before insert, after update) {
    
    if(trigger.isUpdate && trigger.isAfter){
       PropertyBookingHandler.isAfterUpdate(trigger.new);
    }
    if(trigger.isInsert && trigger.isBefore){
        
    }
}
2
  • You can build a flow to handle this requirement. Also, could you please add more context like you are running this piece of code in the trigger?
    – Pavan tej
    Aug 25, 2022 at 15:01
  • 1
    our practice use case said to do this in trigger @Pavantej
    – Kejer
    Aug 25, 2022 at 15:04

1 Answer 1

1

I am quite new here, I am told that I should query in order to get it.

That's okay, we were all new here once.

Let's go over a quick list of problems.

First, don't use try-catch until you determine that you need to do so. Technically, that only includes the insert statement, and you can avoid that with some other error handling.

Second, you're trying to iterate over an empty list. The list of quotes should be outside the for loop.

Third, you have a DML inside a loop. That is almost always bad. The DML operation should only occur outside the loop.

Fourth, lookup fields are populated by Id, not the record's Name field.

Fifth, yes, to get parent data, you need to use a query. This uses the Aggregate-Query-Update Pattern: get the Id values to query, perform a query, then perform any updates. This uses a Map to link the parents to their children.

Here's a rough estimate of what I think your code should look like:

// Aggregate data
Map<Id, Property__c> properties = new Map<Id, Property__c>();
Map<Id, Contact> contacts = new Map<Id, Contact>();
for(Property_Booking__c booking: pbList) {
    properties.put(booking.Property__c, null);
    contacts.put(booking.Contact__c, null);
}
// Query for parent records
properties.putAll([SELECT Type__c FROM Property__c WHERE Id = :properties.keySet()]);
contacts.putAll([SELECT Email FROM Contact WHERE Id = :contacts.keySet()]);

List<Quotation__c> quoList = new List<Quotation__c>();
// Prepare to create new Quotations
for(Property_Booking__c pb: pbList){
    //if the status moves to approved, then a new quotation record should be created, all the fields
    //of the quotation record should take in data from rest of the 3 objects except quoted to customer. 
    //Price should be the quoted price - Case # 8
    if(pb.Status__c == 'Approved'){
        quoList.add(new Quotation__c(
            Booking_Ref__c = pb.Name;
            Property_Name__c = pb.propertyName__c;                        
            Property_Type__c = properties.get(pb.Property__c)?.Type__c;
            Customer_Name__c = pb.customerName__c;
            Acquire_Property_By__c = pb.Acquire_Property_By__c;
            Price__c = pb.Quoted_Price__c;
            Customer_Email__c = contacts.get(pb.Contact__c)?.Email;
        ));
    }
}
// And create the records -- NOTE: if needed, add error handling
insert quoList;
4
  • 1
    I was just learning from the trailheads. thanks for the wonderful insight and advices, I will definitely learn from this. Just wanted to know this line of code. Customer_Email__c = contacts.get(pb.Contact__c)?.Email; what is the "?" called so I can study more about it. Highly appreciated.
    – Kejer
    Aug 25, 2022 at 15:16
  • @Kejer It's not ?, it's ?.. This is the Safe Navigation Operator, and it returns a null value instead of throwing a NullPointerException if the object is null. The docs should explain it well enough. Don't confuse this with . (the dot-operator) for accessing a property or method, or ?, half of the ternary operator ?:, used as a kind of shorthand if-else statement.
    – sfdcfox
    Aug 25, 2022 at 15:25
  • I believe we need to remove quoList.add(newQuoList); line from the above code
    – Pavan tej
    Aug 25, 2022 at 19:35
  • 1
    @Pavantej Indeed. I guess just a copy-paste issue :D
    – sfdcfox
    Aug 25, 2022 at 19:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .