0

I am trying to summarize a JSON

var data = [
  {
    customerName: "Customer1",
    customerId: "1234",
    invoices: [
      {
        id: "647549",
        transactionId: "INV01",
        date: "10/12/2020",
        debit: 371.93,
        dueDate: "09/02/2021"
      }
    ],
    creditmemo: []
  },
  {
    customerName: "Customer5",
    customerId: "5678",
    invoices: [
      {
        id: "631109",
        transactionId: "INV05",
        date: "09/12/2020",
        debit: 206.92,
        dueDate: "08/02/2021"
      },
      {
        id: "664359",
        transactionId: "INV06",
        date: "11/12/2020",
        debit: 91.91,
        dueDate: "10/02/2021"
      }
    ],
    creditmemo: []
  }
];

I have tried several ways, the latest one:

//console.log(data.length);
var data2 = [];
for (let value in data) {
  console.log(data[value].customerName);
  //console.log(data[value]);
  var invoices = [];
  invoices.push(data[value].invoices[0]);
  //console.log(1);
  //console.log(customer);
  /* var max = new Date(
    Math.max.apply(
      null,
      customer.map(function (o) {
        var dateString = o.dueDate;
        var dateParts = dateString.split("/");
        var dateObject = new Date(
          +dateParts[2],
          dateParts[1] - 1,
          +dateParts[0]
        );
        return new Date(dateObject);
      })
    )
  );*/
  var result = [
    invoices.reduce((acc, n) => {
      for (var prop in n) {
        console.log("prop: " + prop);
        if (prop === "debit") {
          if (acc[prop]) {
            acc[prop] += n[prop];
            console.log("OK");
          } else {
            acc[prop] = n[prop];
          }
        } else if (prop === "dueDate") {
          //acc[prop] = max;
        } else {
          acc[prop] = n[prop];
        }
      }
      return acc;
    }, {})
  ];
  data2.push(result);
}
console.log(data2);

I would like to have the following result, sum all the debit of the invoices per customer, get the max date per customer (I didn't find a way to remove the empty property creditmemo

[
  {
    customerName: "Customer1",
    customerId: "1234",
    invoices: [
      {
        id: "647549",
        transactionId: "INV01",
        date: "10/12/2020",
        debit: 371.93,
        dueDate: "09/02/2021"
      }
    ]
  },
  {
    customerName: "Customer5",
    customerId: "5678",
    invoices: [
      {
        id: "631109-664359",
        transactionId: "INV05-INV06",
        date: "11/12/2020",
        debit: 298.83,
        dueDate: "08/02/2021"
      }
  }
];
2
  • what should id value be when a customer has more than two invoices ? Why have a string with the dash (-) separator, such as transactionId: "INV05-INV06", instead an array of id values, such as transactionIds:["INV05","INV06"] Commented Dec 20, 2020 at 22:24
  • the system that will consume this file has only one descriptive field for the invoice, Commented Dec 21, 2020 at 10:49

1 Answer 1

0

It's a fairly straightforward map() of the data array, with a nested reduce() call to refactor the invoices array. The first element in the invoices array is passed as the initial accumulator and it is only refactored if there are multiple in the array. Since we are returning a new object on each map iteration we can simply omit the creditMemo property.

I agree with the commenter regarding storing multiple id properties in arrays rather than concatenated strings – both for later use and simplicity of refactoring.

const summary = data.map(({ customerName, customerId, invoices }) => {
  const debitSummary = invoices.reduce((acc, inv, i) => {
    if (i) {
      acc = {
        ...acc,
        id: acc.id + '-' + inv.id,
        transactionId: acc.transactionId + '-' + inv.transactionId,
        debit: acc.debit + inv.debit,
        date: new Date(inv.date) > new Date(acc.date) ? inv.date : acc.date,
      }
    }
    return acc;
  }, invoices[0]);
  return { customerName, customerId, invoices: [{...debitSummary}] };
});

console.log(summary);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script>
const data = [{ customerName: "Customer1", customerId: "1234", invoices: [{ id: "647549", transactionId: "INV01", date: "10/12/2020", debit: 371.93, dueDate: "09/02/2021" }], creditmemo: [] }, { customerName: "Customer5", customerId: "5678", invoices: [{ id: "631109", transactionId: "INV05", date: "09/12/2020", debit: 206.92, dueDate: "08/02/2021" }, { id: "664359", transactionId: "INV06", date: "11/12/2020", debit: 91.91, dueDate: "10/02/2021" }], creditmemo: [] }];
</script>

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you @pilchard, I have adapted your code to our date format, (DDMMYYY).
That's great, I thought date format might be an issue, glad you made it work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.