Quote Line Items not loading properly

Hi all,

When I'm trying to reload the Quote Line Item (QLI) after a change in the parent record (Quote), the QLI is not loading with the recent value. I need to imply a 3Sec delay for it to load the actual updated value. Following is the scenario:

Quote has a field "Stage" it is a status field which can be changed, on back of any change some "Hooks" will be executed, This HOOKS update some field in QLI in the Product Module. So we need to show the user the updated QLI in Quote after the "Status" field change. 

But unfortunately, After quote moved to sidecar the "QLI is considered as a different component than the Quote" i.e. Quote is a different component and QLI is a different component. (As far as I understood). So the QLI will not be loaded automatically, So we made a change to the "handleSave" of Quote to Reload the QLI.

src/custom/modules/Quotes/clients/base/views/record/record.js

handleSave: function () {

      this._super('handleSave');

      

      // NOTE: The following will run after the record is saved
      // Fetch the current QLI after the state transition change

       // Removing existing QLI from the view and reload else we will end up in duplicating the QLI view

      $('.quote-data-group').remove();


      if (!this.disposed) {
            SUGAR.App.controller.context.reloadData({});
      }
},

So the Above does the Reload of QLI but this is not working all the time may be the HOOKS in the backend take long to update so we don't get the recent vale/changes int he QLI. So in order to overcome the issue, we added a 3 sec wait time.

handleSave: function () {

      this._super('handleSave');

      

      // NOTE: The following will run after the record is saved
      // Fetch the current QLI after the state transition change

       // Removing existing QLI from the view and reload else we will end up in duplicating the QLI view

      $('.quote-data-group').remove();


      if (!this.disposed) {

            // Set the delay to reload the QLI because we trigger hook to update Line Items
            // because of the background process we deliberately delay the load.
            setTimeout(function () {
                  SUGAR.App.controller.context.reloadData({});
             }, 3000); // 3 seconds delay
      }
},

The above code works but not sure about the correct approach to the issue. Any help?

  • [deleted]
    André Lopes
    Lampada Global
    Skype: andre.lampada
  • Hi Aravind Kumar

    What type of logic-hooks are you using? Before-Save or After-Save? I ask because, while trying to create recreate your scenario using after-save hooks I noticed that the updating of a QLI re-triggered the execution of the hook on the Quote. Are you experiencing this as well?

    In any case, I would recommend against the 3 second timer approach because it's unpredictable. Therefore, one solution I came up with was to extend the quote-data-list-groups Layout controller to listen for the data:sync:complete event after the parent Quote has finished saving. Below is the code

    ({
      extendsFrom: "QuotesQuoteDataListGroupsLayout",

      /**
       * @inheritdoc
       */

      initialize: function(options) {
        console.log("extended Quote Data List Groups layout!");
        this._super("initialize", [options]);
      },

      /**
       * @inheritdoc
       */

      bindDataChange: function() {
        this._super("bindDataChange");

        //Apply a listener to blow away this layout's components and re-build
        this.model.on(
          "data:sync:complete",
          function(method, options, request) {
            if (method === "read") {
              return;
            }

            console.log("data:sync:complete fired");

            this.model.fetch({
              fields: ["bundles"],
              success: _.bind(function(model, response, options) {
                //begin by removing the Layout's components
                this.clearOutDataGroupsFromLayout();
                this._onProductBundleChange(model.get("bundles"));
                this.render();
              }, this)
            });
          },
          this
        );
      },

      clearOutDataGroupsFromLayout: function() {
        //Get rid of all the groups
        if (this.groupIds && this.groupIds.length > 0) {
          this.groupIds.forEach(function(dataGroupId) {
            var dataGroupComponent = this._getComponentByGroupId(dataGroupId);
            dataGroupComponent.dispose();
            this.removeComponent(dataGroupComponent);
          }, this);

          this.groupIds = [];
        }
      }
    });

    In this example, we are overriding the bindDataChange method to define our listener to re-fetch the collection of ProductBundles, blow away the existing layout, and then re-build it. It's a bit of a heavy-handled way of achieving what you're looking for because just refreshing the views would cause duplicates to appear. 

    One other option could be to loop over bundles/items setting data on the models silently, then just call a render after all the models have been updated? An example of this being done is with the Quotes/layouts/quote-data-list-groups:: _updateModelWithRecord .

     

    Hope that helps