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
Kenn K.Kenn K. 

Direction in solving multi-object query/Update

I am trying to build a trigger that does a few things and I was hoping I could get the best direction in handling this.

I have 2 objects ("Quote" and "QuoteLine") and a custom setting called "ServiceDate__c" which basically stores 2 information, Country__c and numberOfDays__c. The goal of the trigger is to query aCountry__c field on the QuoteLine object, compare it to country field on the ServiceDate__c object to get the number.
For Example, on the quote line, we store country names like USA. On the Custom setting, we have a map that stores Country, USA with a ServiceDate value of 50. 50 is the number of days that needs to be added to the close date on the quote line. So it's be closeDate 2016-01-20 + 50.

Finally, since there will be a number of closeDate__c fields on the QuoteLine, I would like to query only the UNIQUE CloseDate__c values and update the Quote object.

Sample code would be appreciated.

Tl:dr. Get unique date values on the Quote after calculation happens on the Quoteline object that references a custom setting for more information.

Here is what I have so a far;
 
trigger SB_QuoteAdditionalUpdates on SBQQ__Quote__c (before insert, before update) {

    Set<id> QuoteIds = New Set<id>();

    for (SBQQ__Quote__c SBQuotes : trigger.new){

            QuoteIds.add(SBQuotes.id);
            SBQQ__QuoteLine__c[] SBQuoteLines = [Select country__c, country_code__c, close_date__c, country_employee_construct__c, Employee_CountFormula__c from SBQQ__QuoteLine__c where id IN: QuoteIds];

            if(SBQuoteLines.size()>0){
                for(SBQQ__QuoteLine__c SBQuoteLine : SBQuoteLines ){

                    map<id, OperationalStartDate__c> NumberOfDaysMap = new map <id, OperationalStartDate__c>([select name, Number_Of_Days__c from OperationalStartDate__c where name =: SBQuoteLine.country__c ]);
        }
    }
}

}

 
Best Answer chosen by Kenn K.
pconpcon
Ok, that makes things clearer.  In the code below the lookup field on the QuoteLine__c object is called Quote__c, but if it's not you'll need to update that.
 
trigger QuoteLineUpdateCloseDate on SBQQ__QuoteLine__c (before insert, before update) {
    Map<String, Integer> countryMap = new Map<String, Integer>();
    for (ServiceDate__c sd : ServiceDate__c.getall().values()) {
        countryMap.put(sd.Name, sd.NumberOfDays__c);
    }

    Set<Id> quoteIds = new Set<Id>();

    for (SBQQ__QuoteLine__c line : Trigger.new) {
        if (
            (
                Trigger.isInsert ||
                (
                    line.Country__c != Trigger.oldMap.get(line.Id).Country__c
                )
            ) &&
            countryMap.containsKey(line.Country__c)
        ) {
            quoteIds.add(line.Quote__c);
        }
    }

    Map<Id, SBQQ__Quote__c> quoteMap = new Map<Id, SBQQ__Quote__c>([
        select CloseDate__c
        from SBQQ__Quote__c
        where Id in :quoteIds
    ]);

    for (SBQQ__QuoteLine__c line : Trigger.new) {
        if (
            (
                Trigger.isInsert ||
                (
                    line.Country__c != Trigger.oldMap.get(line.Id).Country__c
                )
            ) &&
            countryMap.containsKey(line.Country__c)
        ) {
            SBQQ__Quote__c quote = quoteMap.get(line.Quote__c);
            line.CloseDate__c = quote.CloseDate__c.addDays(countryMap.get(line.Country__c));
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

All Answers

pconpcon
I have some questions I would like to clarify.  How does your SBQQ__Quote__c relate to your SBQQ__QuoteLine__c item (what is the field name).  Are you trying to update the ServiceDate__c on the Quote__c item or the QuoteLine__c or both?  If both, you will need to do this in two triggers.  In your trigger, you have a where clause for Id on QuoteLine__c but you are using Quote__c ids (this will never work).  Also, you are using a before insert trigger so Id would never exist and you won't have QuoteLine__c items if they are related to Quote__c since the Quote__c has to be created before hand.
Kenn K.Kenn K.
How does your SBQQ__Quote__c relate to your SBQQ__QuoteLine__c

SBQQ__QuoteLine__c is the child of SBQQ__Quote__c
 
Are you trying to update the ServiceDate__c on the Quote__c item or the QuoteLine__c or both.

Ideally, it woud be SBQQ__Quote__c but it'll be both. SBQQ__Quote__c should be updated with the unique values i.e. the quote line will have multiple lines of CloseDate and I would like to update SBQQ__Quote__c with unique values.

I think after insert trigger will help.
I am somewhat stuck and I am pretty sure the code isn't bulkified. Any help whatsoever would be appreciated.

Thanks.

 
pconpcon
So I'm still confused as to the data layout and how you want to update the closed_date__c and what it's suppose to be based off of.  So let's start with the QuoteLine__c object.  The Closed_Date__c field should be equal to some field (??) + ServiceDate__c.NumberOfDays__c (where ServiceDate__c.Country__c equals QuoteLine__c.Country__c).  The same applies to the Quote__c object?
Kenn K.Kenn K.
Sorry for the confusion. I agree, let's start with the QuoteLine Object.
  1. In the QuoteLine Object, there is a field called Country__c and CloseDate__c. 
  2. There is also a custom setting called OperationalStartDate__c that has 2 fields; Name (this is country name) and Number_Of_Days__c.
  3. I would like to Update the value of the close date on the quoteLine. So if the Country__c on the QuoteLine is USA, I would query the custo setting and look for USA, get the Number_Of_Days__c value and add it to the CloseDate__c on the QuoteLine.
I guess let's start with that first.
pconpcon
Ok, that makes things clearer.  In the code below the lookup field on the QuoteLine__c object is called Quote__c, but if it's not you'll need to update that.
 
trigger QuoteLineUpdateCloseDate on SBQQ__QuoteLine__c (before insert, before update) {
    Map<String, Integer> countryMap = new Map<String, Integer>();
    for (ServiceDate__c sd : ServiceDate__c.getall().values()) {
        countryMap.put(sd.Name, sd.NumberOfDays__c);
    }

    Set<Id> quoteIds = new Set<Id>();

    for (SBQQ__QuoteLine__c line : Trigger.new) {
        if (
            (
                Trigger.isInsert ||
                (
                    line.Country__c != Trigger.oldMap.get(line.Id).Country__c
                )
            ) &&
            countryMap.containsKey(line.Country__c)
        ) {
            quoteIds.add(line.Quote__c);
        }
    }

    Map<Id, SBQQ__Quote__c> quoteMap = new Map<Id, SBQQ__Quote__c>([
        select CloseDate__c
        from SBQQ__Quote__c
        where Id in :quoteIds
    ]);

    for (SBQQ__QuoteLine__c line : Trigger.new) {
        if (
            (
                Trigger.isInsert ||
                (
                    line.Country__c != Trigger.oldMap.get(line.Id).Country__c
                )
            ) &&
            countryMap.containsKey(line.Country__c)
        ) {
            SBQQ__Quote__c quote = quoteMap.get(line.Quote__c);
            line.CloseDate__c = quote.CloseDate__c.addDays(countryMap.get(line.Country__c));
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors
This was selected as the best answer
Kenn K.Kenn K.
Wow, that was fast. Let me test it out and will let you know how it goes. I really REALLY appreciate it.