-1

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: "vendor1@gmail.com"}
                },
                {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "vendor2@gmail.com"
                    }
                },
                 {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "vendor2@gmail.com"
                    }
                },
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 700,
                email: "user@gmail.com",
                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: "vendor1@gmail.com"}
                }
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 600, // price redcuded because we divided the product
                email: "user@gmail.com",
                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: "vendor2@gmail.com"
                    }
                },
                 {
                    _id: "622d4e9f9bd88b1599026317",
                    title: "asdas",
                    price: 100,
                    cartQuantity: 5,
                    vendor: {
                        email: "vendor2@gmail.com"
                    }
                },
            ],
            paymentDetails: {
                createdId: 1647145079,
                date: "Sun Mar 13 2022",
                amount: 200, // price redcuded because we divided the product
                email: "user@gmail.com",
                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.

R. Richards
  • 24,603
  • 10
  • 64
  • 64
Jerin
  • 717
  • 1
  • 7
  • 28

2 Answers2

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: "vendor1@gmail.com"
      }
    },
    {
      _id: "622d4e9f9bd88b1599026317",
      title: "asdas",
      price: 100,
      cartQuantity: 5,
      vendor: {
        email: "vendor2@gmail.com"
      }
    },
    {
      _id: "622d4e9f9bd88b1599026317",
      title: "asdas",
      price: 100,
      cartQuantity: 5,
      vendor: {
        email: "vendor2@gmail.com"
      }
    },
  ],
  paymentDetails: {
    createdId: 1647145079,
    date: "Sun Mar 13 2022",
    amount: 700,
    email: "user@gmail.com",
    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
jsN00b
  • 3,584
  • 2
  • 8
  • 21
  • thanks for the explanation. It is working on the js file but when I try to do it with the node js server, it gives me an error that `structuredClone is not defined` – Jerin Mar 23 '22 at 08:58
  • https://developer.mozilla.org/en-US/docs/Web/API/structuredClone are supported from Node 17.0 ,please upgrade and Try – Muhammad Mufeez Ahmed Jul 03 '22 at 06:45
1

Modified Above Answer to Just Split Products without using structured clone , hope this might help

const groupByVendor = arr => (
    arr.map(order => (
      Object.values( // sub-objective 1 - get values from object
        order.products.reduce(
          (previousProduct, product) => ({
            ...previousProduct,
            ...(
              [product.owner] in previousProduct
              ? {
                [product.owner]: {
                  ...previousProduct[product.owner],
                  products: previousProduct[product.owner].products.concat([{...product}]),
                  // sub-objective 2 - add price to existing amount
                }
              }
              : {
                [product.owner]: {
                   // sub-objective 3 - add order info here
                 
                  products: [{...product}]
                }
              }
            )
          }),
          {}
        )
      )
    )).flat()
  );
  
  const rawData = [{
    _id: "622d70a49bd88b1599026318",
    products: [{
        _id: "6223186e2278d4e502f5264a",
        title: "Product number 1",
        price: 600,
        cartQuantity: 1,
        owner: "vendor1@gmail.com"

      },
      {
        _id: "622d4e9f9bd88b1599026317",
        title: "asdas",
        price: 100,
        cartQuantity: 5,
        owner: "vendor2@gmail.com"
        
      },
      {
        _id: "622d4e9f9bd88b1599026317",
        title: "asdas",
        price: 100,
        cartQuantity: 5,
        owner: "vendor2@gmail.com"
        
      },
    ]
  }];
  
  console.log(JSON.stringify(groupByVendor(rawData)));