'What is the best way to split data based on product owners in reactjs or nodejs

I need some idea!

Is there any possible way To separate user orders based on vendor email? I am trying to develop a multi-vendor project where vendors can be able to upload products. I am trying to do when a user orders from a different shop the orders need to be split based on vendor email.

Suppose a customer trying to buy from x vendor and y vendor products. When customers order the products the data look like the below array objects. It is difficult to show vendor orders in their dashboard who ordered your product. So I am trying to split the order based on email also the amount will be divided between the vendors from paymentDetail.amount when splitting the order.

[
        {
            _id: "622d70a49bd88b1599026318",
            products: [
                {
                    _id: "6223186e2278d4e502f5264a",
                    title: "Product number 1",
                    price: 600,
                    cartQuantity: 1,
                    vendor: {email: "[email protected]"}
                },
                {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "[email protected]"
                    }
                },
                 {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "[email protected]"
                    }
                },
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 700,
                email: "[email protected]",
                last4: "4242",
                transaction: "p"
            },
            status: "Pending",
            billing: {
                country: "BD",
                name: "Md. Fathe Karim",
                phone: "+88010000000",
                line1: "Madhabdi",
                city: "Narshingdi",
                postal_code: "1604",
                state: "Bandarban"
            }
        }]

This is my POST request from frontend:

   await fetch('https://guarded-ocean-73313.herokuapp.com/dashboard/orders', {
                method: 'POST',
                headers: {
                    'content-type': 'application/json'
                },
                body: JSON.stringify({
                    products: [...cart], paymentDetails: {
                        createdId: paymentIntent.created,
                        date,
                        amount: paymentIntent.amount,
                        email: emailRef.current?.value,
                        billing: paymentIntent.billing_details,
                        last4: paymentMethod.card.last4,
                        transaction: paymentIntent?.client_secret.slice('_secret')[0]
                    },
                    status: 'Pending',
                    billing: {
                        country: countryRef.current?.value,
                        name: nameRef.current?.value,
                        phone: phoneRef.current?.value,
                        line1: addressRef.current?.value,
                        city: cityRef.current?.value,
                        postal_code: zipRef.current?.value,
                        state: stateRef.current?.value,
                    }
                })
            })
                .then(res => res.json())

This is my order API

 app.post('/dashboard/orders', async (req, res) => {
            const productDetail = req.body
            const result = await unityMartOrdersCollection.insertOne(productDetail)
            res.json(result)
        })

My expectation is something like this:

[
        {
            _id: "622d70a49bd88b1599026318",  // Vendor 1 Order
            products: [
                {
                    _id: "6223186e2278d4e502f5264a",
                    title: "Product number 1",
                    price: 600,
                    cartQuantity: 1,
                    vendor: {email: "[email protected]"}
                }
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 600, // price redcuded because we divided the product
                email: "[email protected]",
                last4: "4242",
                transaction: "p"
            },
            status: "Pending",
            billing: {
                country: "BD",
                name: "Md. Fathe Karim",
                phone: "+88010000000",
                line1: "Madhabdi",
                city: "Narshingdi",
                postal_code: "1604",
                state: "Bandarban"
            }
        },
     {
            _id: "622d70a49bd88b1599026319", // Vendor 2 Order
            products: [

                {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "[email protected]"
                    }
                },
                 {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "[email protected]"
                    }
                },
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 200, // price redcuded because we divided the product
                email: "[email protected]",
                last4: "4242",
                transaction: "p"
            },
            status: "Pending",
            billing: {
                country: "BD",
                name: "Md. Fathe Karim",
                phone: "+88010000000",
                line1: "Madhabdi",
                city: "Narshingdi",
                postal_code: "1604",
                state: "Bandarban"
            }
        }
]

I think it's possible by the reduce method?

can someone give me any idea how can I be able to display the vendor's order into their dashboard? If my thinking is wrong you can share your idea.



Solution 1:[1]

This may be one possible solution to achieve the desired objective:

Code Snippet

const groupByVendor = arr => (
  arr.map(order => (
    Object.values( // sub-objective 1 - get values from object
      order.products.reduce(
        (fin, p) => ({
          ...fin,
          ...(
            [p.vendor.email] in fin
            ? {
              [p.vendor.email]: {
                ...fin[p.vendor.email],
                products: fin[p.vendor.email].products.concat([{...p}]),
                paymentDetails: {
                  ...structuredClone(fin[p.vendor.email].paymentDetails),
                  amount: fin[p.vendor.email].paymentDetails.amount + p.price
                } // sub-objective 2 - add price to existing amount
              }
            }
            : {
              [p.vendor.email]: {
                ...structuredClone(order), // sub-objective 3 - add order info here
                paymentDetails: {
                  ...structuredClone(order.paymentDetails),
                  amount: p.price // sub-objective 2 - set amount to price
                },
                products: [{...p}]
              }
            }
          )
        }),
        {}
      )
    )
  )).flat()
);

const rawData = [{
  _id: "622d70a49bd88b1599026318",
  products: [{
      _id: "6223186e2278d4e502f5264a",
      title: "Product number 1",
      price: 600,
      cartQuantity: 1,
      vendor: {
        email: "[email protected]"
      }
    },
    {
      _id: "622d4e9f9bd88b1599026317",
      title: "asdas",
      price: 100,
      cartQuantity: 5,
      vendor: {
        email: "[email protected]"
      }
    },
    {
      _id: "622d4e9f9bd88b1599026317",
      title: "asdas",
      price: 100,
      cartQuantity: 5,
      vendor: {
        email: "[email protected]"
      }
    },
  ],
  paymentDetails: {
    createdId: 1647145079,
    date: "Sun Mar 13 2022",
    amount: 700,
    email: "[email protected]",
    last4: "4242",
    transaction: "p"
  },
  status: "Pending",
  billing: {
    country: "BD",
    name: "Md. Fathe Karim",
    phone: "+88010000000",
    line1: "Madhabdi",
    city: "Narshingdi",
    postal_code: "1604",
    state: "Bandarban"
  }
}];

console.log(groupByVendor(rawData));

Explanation

The idea is to break down the desired objective into simpler, more-manageable sub-objectives.

Sub-objective 1: A dictionary mapping vendors with orders

  • First, generate an object with props as the vendor email.
  • The values will be the actual order corresponding to the vendor
  • Once this object is created, all we need is the values array

Sub-objective 2: A mechanism to update the paymentDetailss amount

  • If processing a vendor that is not already present, set amount to price
  • If vendor already present, add price to existing amount

Sub-objective 3: Transform the structure of the object

  • The target requires each object in the array have paymentDetails, billing etc.
  • So, when generating the values for the vendor-object/dictionary/map, account for the corresponding transformations

The sub-objectives are marked in the code-snippet for reference.

Please use comments to ask any questions, clarifications, or suggest improvements.

NOTE

  1. This answer employs structuredClone in order to perform deep-cloning of the order object.
  2. My reference was Jeremy's this answer as well as this one

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jsN00b