-2

I am new to Backbone and facing one issue in which i need to calculate the specific values of my models inside my collection.

For the reference, I am pasting the collection of accounts, from which I need to calculate the sum of acquisitionCost, units and netGainLoss of all the models.

i.e after calculating the acquisitionCost, I should get: 1900 and one thing we need to take care is the values are coming in string form like shown in the JSON.

{
    "accounts": [{
            "accountNumber": "AS10000642",
            "assets": [{
                "assetName": "ABCDEF GHIJKLM",
                "isin": "GB0008533564",
                "grossProfit": [{
                    "acquisitionCost": "500",
                    "units": "10",
                    "netGainLoss": "20"
                }]
            }]
        },
        {
            "accountNumber": "AS10000642",
            "assets": [{
                "assetName": "ABCDEF GHIJKLM",
                "isin": "GB0008533564",
                "grossProfit": [{
                    "acquisitionCost": "1000",
                    "units": "10",
                    "netGainLoss": "20"
                }]
            }]
        },
        {
            "accountNumber": "AS10000407",
            "assets": [{
                "assetName": "ABCDEF GHIJKLM",
                "isin": "GB0008533564",
                "grossProfit": [{
                    "acquisitionCost": "400",
                    "units": "10",
                    "netGainLoss": "20"
                }]
            }]
        }
    ]
}
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • 1
    Why not just iterate over the collection and add up the values? Did you try anything? What exactly is blocking you? – T J Jun 19 '17 at 16:03
  • I don't know how to do it . Will be great if u can assist me with it , coz I need to calculate all the values of acquisitionCost, units and netGainLoss of all models – user7386493 Jun 19 '17 at 16:04
  • 1
    Please do some basic research, like "how to loop through backbone collection", and "how to access attributes from backbone model" and make a honest attempt at solving the problem. Please read [ask] – T J Jun 19 '17 at 16:06
  • I tried on my own but the model structure is bit deep , so was not able to otherwise I would have not posted to stackoverflow – user7386493 Jun 19 '17 at 16:15
  • [How to sum values with Backbone collections](https://stackoverflow.com/q/7722048/1218980) and [working with objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects). – Emile Bergeron Jun 19 '17 at 16:17
  • Your question should include a [mcve]. – Emile Bergeron Jun 19 '17 at 16:18
  • I have seen the example , but it only calculates one key , but here in my question I need to calculate multiple , so what is the best way to solve this . – user7386493 Jun 19 '17 at 16:30
  • The `memo` in the example can be an object, so you could put the 3 totals each into a property. – Emile Bergeron Jun 19 '17 at 16:32
  • Can u please update the code and share it with me , coz with my knowledge in that example the memo initial value is zero – user7386493 Jun 19 '17 at 16:35

1 Answers1

-2

One confusing part about backbone is that a particular implementation can be done in a zillion ways but still can be right. So the dev gets to choose the optimal approach to make sure that it is modular and extensible for future use.

Since the data that is presented is deeply nested, it is better that you organise them into collections and models on a collection or a model. That way it can be easy to manipulate and keep adding more functionality on top of it. You can think of a model as a monthership ( Account ) on which smaller ships live ( assets or profit ) . So following that structure, gives us this pattern

Also need to make sure, the account numbers are unique, otherwise, duplicates will not be added to the collection.

// Profit Model
var Profit = Backbone.Model.extend({});

// Asset Model
var Asset = Backbone.Model.extend({
  parse: function(resp) {
    if (resp.grossProfit) {
      this.profit = new Profit(resp.grossProfit);

      delete resp.grossProfit;
    }

    return resp;
  }
});

// Assets Collection
var Assets = Backbone.Collection.extend({
  model: Asset
});

// Account Model
var Account = Backbone.Model.extend({
  idAttribute: 'accountNumber',
  parse: function(resp) {
    if (resp.assets) {
      this.assets = new Assets(resp.assets, {
        parse: true
      });

      delete resp.assets;
    }

    return resp;
  }
});

// Accounts Collections
var Accounts = Backbone.Collection.extend({
  model: Account,
  getTotals: function() {
    var acquisitionCost = 0;
    var units = 0;
    var netGainLoss = 0;

    // iterate over the accounts collections
    this.each(function(account) {
      // iterate over assets collections for each account
      account.assets.each(function(asset) {
        var profit = asset.profit;
        if (profit) {
          acquisitionCost += parseInt(profit.get('acquisitionCost'), 10);
          units += parseInt(profit.get('units'), 10);
          netGainLoss += parseInt(profit.get('netGainLoss'), 10);
        }

      });
    });

    return {
      acquisitionCost: acquisitionCost,
      units: units,
      netGainLoss: netGainLoss
    };
  }
});

var data = {
  "accounts": [{
    "accountNumber": "AS10000642",
    "assets": {
      "assetName": "ABCDEF GHIJKLM",
      "isin": "GB0008533564",
      "grossProfit": {
        "acquisitionCost": "500",
        "units": "10",
        "netGainLoss": "20"
      }

    }
  }, {
    "accountNumber": "AS100006423",
    "assets": {
      "assetName": "ABCDEF GHIJKLM",
      "isin": "GB0008533564",
      "grossProfit": {
        "acquisitionCost": "1000",
        "units": "10",
        "netGainLoss": "20"
      }

    }
  }, {
    "accountNumber": "AS10000407",
    "assets": {
      "assetName": "ABCDEF GHIJKLM",
      "isin": "GB0008533564",
      "grossProfit": {
        "acquisitionCost": "400",
        "units": "10",
        "netGainLoss": "20"
      }

    }
  }]
};

var accounts = new Accounts(data.accounts, {
  parse: true
});

var getTotalData = accounts.getTotals();

console.log("Total acqisition cost - " + getTotalData.acquisitionCost);
console.log("Total units - " + getTotalData.units);
console.log("Total net gain loss - " + getTotalData.netGainLoss);

Check Fiddle

Sushanth --
  • 55,259
  • 9
  • 66
  • 105
  • `parse` shouldn't have side effects and using `delete` in this case is inefficient and unnecessary. Other than that, instantiating a nested structure of model like this on not that big collection will really slow down the browser (to almost a halt on couple hundreds). – Emile Bergeron Jun 19 '17 at 18:38
  • @EmileBergeron The reason of using delete is to remove the data as part of the actual account attribute hash, which is not required anymore since it lives on model directly. The main purpose of the nested structure is to keep it organized and grab them when in necessity. Currently the OP's req is trivial, calculating the count. But what if more props get added with additional functionality. If the nested props keep living on the `account` attr hash, the manipulation gets convoluted since we keep playing around with both objects and model data – Sushanth -- Jun 19 '17 at 18:57
  • Yes, I totally get that to manipulate the data, use it within views, etc., a complex structure would be good, but even then, I would go the lazy init way or computed attributes. In our case here, it's out of scope. – Emile Bergeron Jun 19 '17 at 19:24
  • Thank you so much for your kind assistance "Emile" . But somehow the data that i shared was bit wrong and i have updated the data below, minor modification is that assets is an array not abject with multiple objects inside and grossProfit is also an array of objects. I have updated the data above , please have a look at it and update your code , thank you. – user7386493 Jun 20 '17 at 01:15
  • 1
    Thank you so much sushanth for your help , but can you do one more thing I need to check for duplicate models based on accountNumber and need to merge the assets of those . Example : suppose if we have two models with same account number then we will look for there assets and merge them to one . Can we do this in the example and will be great if you share the code . Thanks – user7386493 Jun 20 '17 at 02:26