Salesforce CPQ – Pull Quote Line Groups into Renewals and Amendments

Hello! If you’re here, you’re looking for how to pull groups into your amendments and/or renewals! You might have come from the Salesforce Idea page or perhaps google search….

App Exchange

This package is now on the AppExchange! Go install it!

Demo

There is a checkbox field, a trigger and a Price Rule involved. Fear not! All of it is right here.

Please NOTE: The Custom Checkbox field and Price Rule are to get around a “Legacy Renewal Service” issue. If you have the Legacy Renewal Service turned on, CPQ will not let the trigger set the Group Line Items field on the Quote object. So we set a custom version of this field (Has_Groups__c) to TRUE and then the Price Rule conditions on this custom field and checks the Group Line Items CPQ field on the Quote. If this Price Rule does not run, you will get a forever spinning “waiting” dots image because of a javascript error. Essentially, there are groups on the quote but the line editor doesn’t think there is because the checkbox is unchecked so it kabooms and waits forever.

Price Rule
This Price Rule is only for the legacy Renewal service (see the second note at the top). The new Renewal service does not have an issue with setting the Grouped Line Items checkbox on Quote but the legacy service does. We have no idea which service you’re using so this solution accommodates both!

Price Rule Name: Quote – Inject TRUE to Group Line Items

Special Fields

Here are some special fields you can create to get more control over when you pull line groups into renewals and amendments. They can be formula fields or editable checkboxes. You can then apply your own logic to determine when to pull groups.

Note: if these fields do not exist, the system will pull groups into renewals and amendments, respectively, all of the time.

FieldObject/LocationData TypeDescription
Pull_Line_Groups_RenewalsContractCheckboxCreate a checkbox field! This can be a formula field or editable field. When checked, CPQ will pull Quote Line Groups from the original contract into your renewal Quotes.
Pull_Line_Groups_AmendmentsContractCheckbox Create a checkbox field! This can be a formula field or editable field. When checked, CPQ will pull Quote Line Groups from the original contract into your amendment Quotes.

78 thoughts on “Salesforce CPQ – Pull Quote Line Groups into Renewals and Amendments

  1. This is great, thanks. For users out there who use Service Cloud for CPQ, you can use the exact same code and rules, but the formula field needs to change a little bit. Here’s that formula:

    IF( NOT( ISBLANK( SBQQSC__UpgradedContractLine__c ) ),
    SBQQSC__UpgradedContractLine__r.SBQQSC__QuoteLine__r.SBQQ__Group__c ,
    IF( NOT( ISBLANK( SBQQSC__RenewedContractLine__c ) ),
    SBQQSC__RenewedContractLine__r.SBQQSC__QuoteLine__r.SBQQ__Group__c ,

    )
    )

  2. Question on the price rule – in your experience do you not need a “false” pairing to the “true” you created? In other words, if I want to un-group a renewal quote, is it enough to delete the groups and save, or do I need a price rule that sets grouping to false based on a sumvar count of 0?

    1. Ah yes, this is a good thought. How to “undo” this thing… Will the rule kill my ungroupings or set something wonky… The short answer is no. The long answer is: CPQ usually manages this checkbox for you as you group/ungroup in the line editor. But, for some reason, it does not do this when groups get inserted via trigger like the above. It omits the evaluation of grouped lines and setting of this field, hence the price rule is needed. In the trigger, it always thinks there are no grouped lines.

  3. Hi Dennis,

    It’s great to be able to pull the groups into the amendment and renewal quotes! I am testing the code, but when I tried to open the quotes updated by the code, the quote line editor failed to load (just hang there), did you experience this before?

    Thanks.

    Jacky

    1. I had to hit the calculate button manually on the quote page, after the calculation completes, then get into the QLE. Not sure if it is something from our sandbox.

      1. Have you implemented the Price Rule? This will happen if the Price Rule isn’t firing or isn’t there.

      2. Ah! This is the thing that is missing! In the package settings, set “Calculate Immediately” to true.

        1. I was experiencing the same issue and setting Filter Value explicitely to NULL for the summary variable instead of leaving it blank did the trick for me!

        2. I’m also encountering the same issue. I have to hit calculate first before the group line items to be set to TRUE.

          1. There is a solution! In CPQ Package Settings, set Calculate Immediately to true!

        3. Yes, I have implemented Price rule and activated.
          I noticed that ‘Group Line Items’ in Quote is not updating to TRUE. This is the reason it just keeps loading on Quote Line Editor. When I manually make it to TRUE on the amendment Quote, the line editor loads and retains the Groups.

          1. Thank you Yamin S. Your solution works!. I have explicitly given NULL in the Filter Value of a summary variable. Thank you D P 🙂

          2. This is not working as expected when there is a package (product with product options)

  4. Dennis, I have activated the Price Rule but it will not fire automatiaclly after a renewal or amendment causing the QLE to be blank. I need to edit and save the QL to force a recalulation then it works great. From the other notes it appears this has happened to others. Was a solution ever found for this? Thanks Greg

    1. This is a great idea. Will update the article Monday morning to incorporate this. Thanks for the feedback!

  5. Adding on to Chris’ thoughts, is there any way to use twin fields and/or QCP to simplify or eliminate the use of code, and to minimize performance impacte?

          1. I have not! Even if it were a QCP, it would involve an APEX web service that does the group creating. The next evolution of this solution will be a callable method that is called by a scheduled process builder action so the code is executed outside of the standard CPQ processing.

  6. I am still not able to get this to work. One of the 2 issues happens:

    1) It just spins when I do the amendment (in that case, everything gets created as expected, just have to click out and back in like others have mentioned). I have Calculate Immediately on.

    2) When I tried to do the ‘NULL’ instead of leaving filter value blank in the summary variable (as some mentioned resolved their issue), it doesn’t spin anymore but it just groups all of my lines into 1 big group rather than splitting them out as expected. I’m not overly shocked by this considering every line is going to have SBQQ__Group__c != ‘NULL’ since its either an ID or blank and would recommend anyone else who tried this method to re-look and make sure it is functioning correctly.

    Any help would be greatly appreciated.

    1. 1) The spinning happens because the Group Line Items field is not checked. The explicit NULL resolves this.
      2) I’ve updated the trigger code. Try it and let me know if it’s still is grouping in one big group.

      The reason 2 was happening is because it is not creating the groups (bug in code) and then the price rule flags the quote as grouped so the line editor makes a group and assigns it to every line.

      1. Hello, this is great! Thank you for sharing this information.

        I am trying this out in the Sandbox and sometimes I am getting an error of ‘No metadata was retrieved for field null.Name’ from the Quote Line Editor screen. Is that related to this? I updated the code per your note, but still seem to be seeing the error.

        Thanks!

      2. Explicit NULL resolved the issue – What exactly you changed? I am also facing the spinning issue in the QLE on amendment.

  7. Hi DP, do you have a test class for the helper class? I am not a developer and need some help in doing this one.

  8. Hi Denise, thank you a bunch for writing this article. I have followed the instructions that you provided, however when I go to test this, I created a quote with 2 groups, contracted it, and amended it, however, my amendment quote only contains one group always called “Group 1”; I am not getting any error messages or hangups. Any ideas what the problem could be? Thank you in advance.

    1. Hi Brian,

      For some reason, your groups are not being created by the trigger. Then the price rule is setting it as grouped. I am going to re-implement this in a fresh org to see if I can reproduce this issue as it is happening to a few of you.

      1. Hi Dennis, thanks for the help on this, however, I am still seeing issues.

        – When I try to amend an existing contract with groups, CPQ tries to load the line editor page but instead, the page just tries to load forever.
        – I am still seeing odd formatting loading on the line editor page for segmented products
        – Creating a new quote always creates a group; I think you said in another post that for now it is required, however our business case doesn’t always require groups on quotes, and grouping does affect the quote line section on quote templates, so if something could be done about that, that would be great.

        Thanks!
        -Brian

        1. Yes I am looking for solutions to the “groups are required” part of this. For now there is no solution as CPQ unchecks that box if I check it directly in the code.

          I’ll be adding segmented products to my testing agenda for the next release of this solution.

  9. Hi Dennis,

    Even after adding the NULL in the filter value of the summary variable and updating to your most recent Apex class and trigger code, my groups are not persisting and are being combined into one group for both Renewal and Amendments. I have checked to ensure Calculate Immediately is checked in the CPQ settings, the price rule is active and the trigger is active. I there anything else I could check?

    Thanks so much.

  10. Hi Dennis,

    After going through the latest here in terms of the Apex class, trigger and adding NULL in the summary variable. We are experiencing the issue where the groups are combined in to one group. Calculate Immediately is check on as well. Is there anything else we can check or that might cause this? Note, posting again as I am not sure my original post went through.

    Thanks so much.

  11. Hi Dennis,

    Another thing I am now noticing is when I go to add products in the QLE, when I add a product it is automatically put into a group. Hitting ungroup does not take the product out of the group. It’s as if I am forced to use groups.

    Thanks for any thoughts here. Matt

    1. Hey Matt,

      A couple things about all the comments!

      – For some reason, your groups are not being created by the trigger. Then the price rule is setting it as grouped. I am going to re-implement this in a fresh org to see if I can reproduce this issue as it is happening to a few of you.

      – Yes the price rule makes it so that all quotes have groups. You can put in a price condition so only renewal/amendment quotes with original lines that have groups fire this rule.

      1. Thanks, Dennis, I really appreciate the help! Some additional details- it seems like whenever any quote is created, there is always a “Group 1” present that cannot be removed. Also, the formatting for our segmented products seems to get wacky.

    2. FYI: This solution requires groups. The Price Rule forces it. I am actively looking for a way around this but for now, you’re forced into groups.

  12. Hi DP,

    We used this and working as expected but after deployment instead of just recreating the QL groups, it is also creating extra groups. For example, 4 QL groups on the Original Quote, on Amendment/Renew it is now 8.

  13. Hi DP,

    Thanks for the fix. We used this and working as expected but after re-amendment, grouping not working as expected, it is also creating extra groups. For example, 2 QL groups on the Original Quote, on Amendment/Renew it is now 4 and if it has 4 QL groups its creating 8 new grouping.

    1. Yes! This is a known bug. I’ll be reviewing the solution to accommodate this. Thanks for the feedback!

  14. Hi Dennis,
    This is such an important functionality, unfortunate that it is not out of the box. Thank you for posting this solution here. Just wanted to ask if you are aware of any other workarounds to the endless spinning upon entering the Quote Line Editor and once in the QLE, the Quote Groups not persisting. I see that this is an issue that other users have faced, I have tried turning on Calculate Immediately and explicitly using NULL in the Summary Variable but to no avail.

    Thank you for any thoughts,
    Erik

    1. Hi Erik!

      The endless spinning is because of the “Group Line Items” checkbox not being checked. It turns out, currently, to have this solution, you must always check this box on all Quotes for it to work properly at all times.

  15. Hello! when trying to Amend a Contract (the original Quote has Subscription Lines and Asset Lines), the Assets Quote Lines on the Amended Quote do not have a value on the SBQQ__Group__c field. This resulted in the endless spinning because some of the Quote Lines have blank Groups.

  16. Hello! Does this also preserve group for renew subscriptions on the quote line editor? Is there a way to achieve that? Thanks!

    1. Yes! This will pull all your original groups from your original quote into the renewal quote and assign the new group records to all of the appropriate quote lines.

  17. Hello! So having issues with Renewed Quotes…

    My company does Subscriptions per Year in Quote Line Groups. So we use the Subscription Start Date and Subscription End Date on QLGs heavily as that becomes the New Effective Subscription Date.
    That means a bundle for 3 years starting 5/25/2022 – 5/24/2025 would be created across each Group with its individual line such that:

    Year 1 QLG: Bundle A – Start Date 5/25/2022 End Date 5/24/2023
    Year 2 QLG: Bundle A – Start Date 5/25/2023 End Date 5/24/2024
    Year 3 QLG: Bundle A – Start Date 5/25/2024 End Date 5/24/2025

    That being said, when a Contract is Activated and the Opportunity is Closed Won – the Renewal Opp is created and for testing, I check the Renewal Quote checkbox.

    The problem on the Renewed Quote I’m seeing is :

    A. The QLE Screen is stuck on Loading
    B. Looking at the Quote Lines on the Created Quote all have incorrect Effective Start Dates / End Date

    For Example

    Year 1 QLG: Bundle A – Start Date 5/25/2022 End Date 5/24/2023 – Original Quote Line
    Year 1 QLG: Bundle A – Start Date 5/25/2023 End Date 5/24/2023 – Renewed Quote Line

    So all my Dates are screwed up – wondering if there’s a solution to this or if I should just clear this out? Or not sure tbh, because if the Renewal Dates don’t continue on from the Original Quote where
    Renewed Start Date for Year 1 QLG Bundle A would be: Effective Start (Original Quote Line) + 36 or at least follow the Subscription Term in Months for the QLG?

    1. Hey Ann Marie Jo! The stuck on loading is usually the Group Line Items checkbox not being checked. But it could also be because one or more of your lines don’t have a QLG? Check to see if that’s the case. If so, I can create this scenario in my org and debug through to see what the deal is. Sorry for the late response!

      1. Hiya –

        So for some reason, the QLG Groups are carrying over for most QLI but not some components. Is there a reason why this is happening? This is tied to the same issue I posted.

        Would love to talk to you about this – maybe I could book your services for an hour or two’s worth of consult?

  18. I have used the code provided and created the price rule and ran the script too. On renewal quote, I can see the Group Line Items field is checked as well. However, I am still seeing a forever waiting dots on quote line editor. Can you help me fix this?

    1. Hey Vaibhav! The stuck on loading is usually the Group Line Items checkbox not being checked. But it could also be because one or more of your lines don’t have a QLG? Check to see if that’s the case. If so, I can create this scenario in my org and debug through to see what the deal is. Sorry for the late response!

  19. Heya,

    The issue I’m seeing is that we’re when an Amendment is created on a Renewal Opp; the groups are inheriting from the Original Quote and not the renewal.

    e.g. Quote has 3 lines running from April 1st – June 31st this is then contracted

    A Renewal opp is generated from the original contract and the Quote is updated to have 3 lines running July 1st – September 30th this in turn is also contracted.

    When an amendment is made on the renewal opp the Quote Line groups are showing dates for April 1st – June 31st and not July 1st – September 30th

  20. Hello!

    I am running into an issue when running a second amendment on the Contract.

    Error Message: Error:Error while saving Quote Lines:SBQQ.ValidationException: [“QuoteTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 8 with id a8L5b000003wSsOEAU; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Line 9: Select a start date on or after ’11/15/2022′.: [] Class.QuoteTriggerHelper.insertMissingAmendmentRenewalLineGroups: line 142, column 1 Class.QuoteTriggerHelper.doInsertMissingAmendmentRenewalLineGroups: line 14, column 1 Class.QuoteTriggerHelper.runTriggers: line 6, column 1 Trigger.QuoteTrigger: line 3, column 1”] (System Code)

    The original quote has 3 QLG divided into Year 1, Year 2, Year 3 spanning 4/30/2021-4/29/2024

    The amendment was done 11/15/2022 to the end of the contract term.

    We are trying to do another amendment, but are running into that error message.
    It seems to be related to that amended quote that’s been contracted into the original contract.

    I checked that Quote and it does have Groups as well called Year 2, Year 3.

    What is the fix for this sort of situation? Thank you!

  21. Hello, thanks for sharing this code. We ran into a bug where it doesn’t work for amendments that have bundles. CPQ inserts the bundle parent quote lines first, and then the child quote lines – at least in the contract we were using. The code runs when the bundle parent quote lines are inserted, due to a parent quote update, and sets the SBQQ__Group__c field on those quote lines. Then when the other quote lines are inserted, it skips them, because it’s already set up the groups on the quote and flagged the quote appropriately. That results in some child quote lines having a missing SBQQ__Group__c value, and there being an error in the amendment workflow

  22. Hello Dennis,

    Thanks for sharing this solution.

    We have a use case for Group with having Startdate and Subscription Term need to set , for which we used QCP.

    With this logic added , when we do an amendment with group , it will not load the Quote lines and continuously show the spinner on the screen.

    Please share your thoughts.

    1. Hey sorry for the late reply! Hope you had a great summer! I would need to see your actual setup to make any recommendations. However, the infinite spinner happens when the checkbox on Quote for grouped lines is unchecked when there are lines that are grouped.

    2. The continuous spinner happens when you have legacy contracting service enabled and don’t have the price rule for flagging the quote as having groups.

  23. Hi Dennis,

    Thanks for sharing this! I am currently implementing this but am running into an issue that I see has been mentioned on this page before. After amending once with the addition of let’s say 1 product per group in a total of 3 groups, when I go to amend a second time, the new products that were added in the first amendment have been moved to newly created groups.

    Has there been any update regarding this? Appreciate your time and effort!

    Best,
    Thomas

    1. Hi Thomas!

      I have a new version in the hopper ready to release to the appexchange. Sit tight! This one was a doozy to solve but it’s working!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.