0

I want to prepare an array for payment collection report I have a response array like:

orderDate:[{ 
    date: 21-01-20,
    sales: 20,
    method: Razorpay,
    sub: 1
},{ 
    date: 21-01-20,
    sales: 20,
    method: Simpl,
    sub: 1
},{ 
    date: 21-01-20,
    sales: 20,
    method: Razorpay,
    sub: 1
},{ 
    date: 21-01-20,
    sales: 20,
    method: Cash,
    sub: 1
},{ 
    date: 21-01-20,
    sales: 20,
    method: Credit,
    sub: 1
},{ 
    date: 22-01-20,
    sales: 10,
    method: Credit,
    sub: 1
},{ 
    date: 22-01-20,
    sales: 20,
    method: Razorpay,
    sub: 1
}];

And I have payment method array

paymentMethods:[Razorpay, Simpl, Paytm, Other];

I want to prepare a final array like:

final:[{
    date: 21-01-20,
    revenue:[40, 20, 0, 40] //method wise sum of sales for the respected date
},{
    date: 22-01-20,
    revenue:[20, 0, 0, 10] //method wise sum of sales for the respected date
}]

If no data found for a respected method then push 0 value at the index of that method

Thank you for the help

Haresh Makwana
  • 177
  • 1
  • 12
  • Does this answer your question? [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – AZ_ Jan 24 '20 at 07:25
  • AZ_ Not exactly because if no data found for a particular method then I have to push 0 value on that methods position, In short, I need the array filled exactly the length of methods – Haresh Makwana Jan 24 '20 at 07:29

2 Answers2

1

Try the below code:

var orderDate = [{
  date: "21 - 01 - 20",
  sales: 20,
  method: "Razorpay",
  sub: 1
}, {
  date: "21 - 01 - 20",
  sales: 20,
  method: "Simpl",
  sub: 1
}, {
  date: "21 - 01 - 20",
  sales: 20,
  method: "Razorpay",
  sub: 1
}, {
  date: "21 - 01 - 20",
  sales: 20,
  method: "Cash",
  sub: 1
}, {
  date: "21 - 01 - 20",
  sales: 20,
  method: "Credit",
  sub: 1
}, {
  date: "22 - 01 - 20",
  sales: 10,
  method: "Credit",
  sub: 1
}, {
  date: "22 - 01 - 20",
  sales: 20,
  method: "Razorpay",
  sub: 1
}];

var paymentMethods = ["Razorpay", "Simpl", "Paytm", "Other"];

var final = [];

orderDate.forEach(dateItem => {
  var logItem = final.find(x => x.date === dateItem.date);

  if (!logItem) {
    logItem = {
      date: dateItem.date,
      revenue: [0, 0, 0, 0]
    }
    final.push(logItem);
  }
  
  
  var methodIndex = paymentMethods.indexOf(dateItem.method);
  
  if (methodIndex === -1) {
    methodIndex = paymentMethods.indexOf("Other")
  }
  
  logItem.revenue[methodIndex] = logItem.revenue[methodIndex] + dateItem.sales
});

console.log(final);
1

You can group by using Array.prototype.reduce.

let orderDate = [{
 date: '21 - 01 - 20',
 sales: 20,
 method: 'Razorpay',
 sub: 1
}, {
 date: '21 - 01 - 20',
 sales: 20,
 method: 'Simpl',
 sub: 1
}, {
 date: '21 - 01 - 20',
 sales: 20,
 method: 'Razorpay',
 sub: 1
}, {
 date: '21 - 01 - 20',
 sales: 20,
 method: 'Cash',
 sub: 1
}, {
 date: '21 - 01 - 20',
 sales: 20,
 method: 'Credit',
 sub: 1
}, {
 date: '22 - 01 - 20',
 sales: 10,
 method: 'Credit',
 sub: 1
}, {
 date: '22 - 01 - 20',
 sales: 20,
 method: 'Razorpay',
 sub: 1
}];

let paymentMethods = { 'Razorpay': 0, 'Simpl': 0, 'Paytm': 0, 'Other': 0 };

let out = orderDate.reduce((acc, curr) => {
acc[curr.date] = acc[curr.date] ? acc[curr.date] : { ...paymentMethods };
if(acc[curr.date].hasOwnProperty(curr.method)) {
 acc[curr.date][curr.method] = curr.sales;
}
return acc;
}, {});
let finalObject = Object.entries(out).map(([date, value]) => ({ date, revenue: Object.values(value) }))
console.log(finalObject)
AZ_
  • 3,094
  • 1
  • 9
  • 19