skip to Main Content

I have an array of invoice objects that I want to turn into a distinct array of just the supplier ID, supplier name and a reduced total across all the invoices from each distinct supplier where the status equals 3. Here is what I have so far:

const invoices = [
  {
    invoiceNumber: "12345678",
    invoiceDate: "12th September 2023",
    supplierId: "SUP123",
    supplierName: "Roger Enterprises Ltd",
    invoiceTotal: 1200,
    status: 3
  },
  {
    invoiceNumber: "87654321",
    invoiceDate: "10th September 2023",
    supplierId: "SUP123",
    supplierName: "Roger Enterprises Ltd",
    invoiceTotal: 800,
    status: 1
  },
  {
    invoiceNumber: "13572468",
    invoiceDate: "8th September 2023",
    supplierId: "SUP123",
    supplierName: "Roger Enterprises Ltd",
    invoiceTotal: 1000,
    status: 3
  },
  {
    invoiceNumber: "AB1234",
    invoiceDate: "12th September 2023",
    supplierId: "SUP456",
    supplierName: "Steve Systems Ltd",
    invoiceTotal: 500,
    status: 3
  },
  {
    invoiceNumber: "XY5678",
    invoiceDate: "4th September 2023",
    supplierId: "SUP456",
    supplierName: "Steve Systems Ltd",
    invoiceTotal: 700,
    status: 3
  }
]

Here is the desired output:

[
  {
    supplierId: "SUP123",
    supplierName: "Roger Enterprises Ltd",
    invoicesTotal: 2200
  },
  {
    supplierId: "SUP456",
    supplierName: "Steve Systems Ltd",
    invoicesTotal: 1200
  }
]

I’ve managed to piece together getting an array of distinct suppliers but am now stuck on how to reduce the relevant invoice totals from the original invoice array and insert that into the relevant supplier object in the arr array:

const distinctSupplierMap = new Map(
      invoices.map((invoice) => [invoice.supplierId, invoice])
    );
const distinctSuppliersFilter = [...distinctSupplierMap.values()];
let arr = [];
    distinctSuppliersFilter.map((distSupp) => {
      arr.push({
        supplierId: distSupp.supplierId,
        supplierName: distSupp.supplierName,
      });
    });

As always, any help is greatly appreciated

3

Answers


  1. Use reduce like this:

    /*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/ 
    const invoices = [  {    invoiceNumber: '12345678',    invoiceDate: '12th September 2023',    supplierId: 'SUP123',    supplierName: 'Roger Enterprises Ltd',    invoiceTotal: 1200,    status: 3,  },  {    invoiceNumber: '87654321',    invoiceDate: '10th September 2023',    supplierId: 'SUP123',    supplierName: 'Roger Enterprises Ltd',    invoiceTotal: 800,    status: 1,  },  {    invoiceNumber: '13572468',    invoiceDate: '8th September 2023',    supplierId: 'SUP123',    supplierName: 'Roger Enterprises Ltd',    invoiceTotal: 1000,    status: 3,  },  {    invoiceNumber: 'AB1234',    invoiceDate: '12th September 2023',    supplierId: 'SUP456',    supplierName: 'Steve Systems Ltd',    invoiceTotal: 500,    status: 3,  },  {    invoiceNumber: 'XY5678',    invoiceDate: '4th September 2023',    supplierId: 'SUP456',    supplierName: 'Steve Systems Ltd',    invoiceTotal: 700,    status: 3,  },];
    const o = invoices.reduce((m, c) => {
      const old = m.get(c.supplierId) ?? {
        supplierId: c.supplierId,
        supplierName: c.supplierName,
      };
      old.invoiceTotal =
        (old.invoiceTotal ?? 0) + (c.status === 3 ? c.invoiceTotal : 0);
      return m.set(c.supplierId, old);
    }, new Map());
    console.log([...o.values()]);
    <!-- https://meta.stackoverflow.com/a/375985/ -->    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
    Login or Signup to reply.
  2. You’ll want two steps

    1. Reduce and sum totals by tracking supplierId in a map, only adding when status === 3
    2. Extract the values from your map
    const invoices = [{"invoiceNumber":"12345678","invoiceDate":"12th September 2023","supplierId":"SUP123","supplierName":"Roger Enterprises Ltd","invoiceTotal":1200,"status":3},{"invoiceNumber":"87654321","invoiceDate":"10th September 2023","supplierId":"SUP123","supplierName":"Roger Enterprises Ltd","invoiceTotal":800,"status":1},{"invoiceNumber":"13572468","invoiceDate":"8th September 2023","supplierId":"SUP123","supplierName":"Roger Enterprises Ltd","invoiceTotal":1000,"status":3},{"invoiceNumber":"AB1234","invoiceDate":"12th September 2023","supplierId":"SUP456","supplierName":"Steve Systems Ltd","invoiceTotal":500,"status":3},{"invoiceNumber":"XY5678","invoiceDate":"4th September 2023","supplierId":"SUP456","supplierName":"Steve Systems Ltd","invoiceTotal":700,"status":3}];
    
    const arr = Object.values(
      invoices.reduce(
        (map, { supplierId, supplierName, invoiceTotal, status }) => {
          map[supplierId] ??= { supplierId, supplierName, invoicesTotal: 0 };
          if (status === 3) {
            map[supplierId].invoicesTotal += invoiceTotal;
          }
          return map;
        },
        {},
      ),
    );
    
    console.log(arr);
    .as-console-wrapper { max-height: 100% !important; }
    Login or Signup to reply.
  3. You can first use filter to filter out the object where status is not 3 then use reduce to create a an object where the key will be the supplierId. At the end use Object.values to get an array out of the object

    const invoices = [{
        invoiceNumber: "12345678",
        invoiceDate: "12th September 2023",
        supplierId: "SUP123",
        supplierName: "Roger Enterprises Ltd",
        invoiceTotal: 1200,
        status: 3
      },
      {
        invoiceNumber: "87654321",
        invoiceDate: "10th September 2023",
        supplierId: "SUP123",
        supplierName: "Roger Enterprises Ltd",
        invoiceTotal: 800,
        status: 1
      },
      {
        invoiceNumber: "13572468",
        invoiceDate: "8th September 2023",
        supplierId: "SUP123",
        supplierName: "Roger Enterprises Ltd",
        invoiceTotal: 1000,
        status: 3
      },
      {
        invoiceNumber: "AB1234",
        invoiceDate: "12th September 2023",
        supplierId: "SUP456",
        supplierName: "Steve Systems Ltd",
        invoiceTotal: 500,
        status: 3
      },
      {
        invoiceNumber: "XY5678",
        invoiceDate: "4th September 2023",
        supplierId: "SUP456",
        supplierName: "Steve Systems Ltd",
        invoiceTotal: 700,
        status: 3
      }
    ].filter(curr => curr.status === 3).reduce((acc, curr) => {
    
      const supplierId = curr.supplierId;
      if (!acc[supplierId]) {
        acc[supplierId] = {
          supplierId: curr.supplierId,
          supplierName: curr.supplierName,
          invoicesTotal: curr.invoiceTotal
        }
      } else {
        acc[supplierId] = {
          ...acc[supplierId],
          invoicesTotal: acc[supplierId].invoicesTotal + curr.invoiceTotal,
    
        }
    
      }
      return acc;
    
    }, {});
    
    console.log(Object.values(invoices))
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search