Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backend for orders #405

Merged
merged 3 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 38 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,29 +259,13 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Arindam</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jainaryan04">
<img src="https://avatars.githubusercontent.com/u/138214350?v=4" width="100;" alt="jainaryan04"/>
<br />
<sub><b>Aryan Ramesh Jain</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/haseebzaki-07">
<img src="https://avatars.githubusercontent.com/u/147314463?v=4" width="100;" alt="haseebzaki-07"/>
<br />
<sub><b>Haseeb Zaki</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/alo7lika">
<img src="https://avatars.githubusercontent.com/u/152315710?v=4" width="100;" alt="alo7lika"/>
<br />
<sub><b>alolika bhowmik</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Ashwinib26">
<img src="https://avatars.githubusercontent.com/u/149402720?v=4" width="100;" alt="Ashwinib26"/>
Expand All @@ -296,6 +280,8 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Mahera Nayan</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/tejasbenibagde">
<img src="https://avatars.githubusercontent.com/u/124677750?v=4" width="100;" alt="tejasbenibagde"/>
Expand All @@ -310,22 +296,13 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Tyarla Shirisha</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/VinayLodhi1712">
<img src="https://avatars.githubusercontent.com/u/135756009?v=4" width="100;" alt="VinayLodhi1712"/>
<br />
<sub><b>Vinay Anand Lodhi</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Amnyadav">
<img src="https://avatars.githubusercontent.com/u/127370497?v=4" width="100;" alt="Amnyadav"/>
<br />
<sub><b>Aman Yadav</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/NilanchalaPanda">
<img src="https://avatars.githubusercontent.com/u/110488337?v=4" width="100;" alt="NilanchalaPanda"/>
Expand All @@ -334,17 +311,10 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
</a>
</td>
<td align="center">
<a href="https://github.com/Suhas-Koheda">
<img src="https://avatars.githubusercontent.com/u/72063139?v=4" width="100;" alt="Suhas-Koheda"/>
<br />
<sub><b>Suhas Koheda</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Sumanbhadra">
<img src="https://avatars.githubusercontent.com/u/93245252?v=4" width="100;" alt="Sumanbhadra"/>
<a href="https://github.com/haseebzaki-07">
<img src="https://avatars.githubusercontent.com/u/147314463?v=4" width="100;" alt="haseebzaki-07"/>
<br />
<sub><b>Suman Bhadra</b></sub>
<sub><b>Haseeb Zaki</b></sub>
Comment on lines +314 to +317
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update contributor information consistently.

The changes to contributor information are mostly correct, but there are some inconsistencies:

  1. Haseeb Zaki is still present in the contributors list despite being marked as removed in the summary
  2. Some GitHub usernames don't match their display names, which could cause confusion

Please make the following adjustments:

  1. Remove Haseeb Zaki's entry as indicated in the summary
  2. Ensure GitHub usernames match display names for consistency:
- <a href="https://github.com/PavanTeja2005">
-   <sub><b>PavanTeja2005</b></sub>
+ <a href="https://github.com/Suhas-Koheda">
+   <sub><b>Suhas Koheda</b></sub>

Also applies to: 330-333, 337-340, 351-356, 358-361, 380-386

</a>
</td>
<td align="center">
Expand All @@ -354,22 +324,22 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Sawan kushwah </b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/PavanTeja2005">
<img src="https://avatars.githubusercontent.com/u/98730339?v=4" width="100;" alt="PavanTeja2005"/>
<a href="https://github.com/Suhas-Koheda">
<img src="https://avatars.githubusercontent.com/u/72063139?v=4" width="100;" alt="Suhas-Koheda"/>
<br />
<sub><b>PavanTeja2005</b></sub>
<sub><b>Suhas Koheda</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/sajalbatra">
<img src="https://avatars.githubusercontent.com/u/125984550?v=4" width="100;" alt="sajalbatra"/>
<a href="https://github.com/Jay-1409">
<img src="https://avatars.githubusercontent.com/u/166749819?v=4" width="100;" alt="Jay-1409"/>
<br />
<sub><b>Sajal Batra</b></sub>
<sub><b>Jay shah</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/vishnuprasad2004">
<img src="https://avatars.githubusercontent.com/u/116942066?v=4" width="100;" alt="vishnuprasad2004"/>
Expand All @@ -378,10 +348,17 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
</a>
</td>
<td align="center">
<a href="https://github.com/Jay-1409">
<img src="https://avatars.githubusercontent.com/u/166749819?v=4" width="100;" alt="Jay-1409"/>
<a href="https://github.com/sajalbatra">
<img src="https://avatars.githubusercontent.com/u/125984550?v=4" width="100;" alt="sajalbatra"/>
<br />
<sub><b>Jay shah</b></sub>
<sub><b>Sajal Batra</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/PavanTeja2005">
<img src="https://avatars.githubusercontent.com/u/98730339?v=4" width="100;" alt="PavanTeja2005"/>
<br />
<sub><b>PavanTeja2005</b></sub>
</a>
</td>
<td align="center">
Expand All @@ -391,13 +368,22 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Abhijit Motekar</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Navneetdadhich">
<img src="https://avatars.githubusercontent.com/u/156535853?v=4" width="100;" alt="Navneetdadhich"/>
<br />
<sub><b>Navneet Dadhich</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/VinayLodhi1712">
<img src="https://avatars.githubusercontent.com/u/135756009?v=4" width="100;" alt="VinayLodhi1712"/>
<br />
<sub><b>Vinay Anand Lodhi</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/lade6501">
<img src="https://avatars.githubusercontent.com/u/83055827?v=4" width="100;" alt="lade6501"/>
Expand All @@ -412,8 +398,6 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>MD REHAN</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/T-Rahul-prabhu-38">
<img src="https://avatars.githubusercontent.com/u/167653990?v=4" width="100;" alt="T-Rahul-prabhu-38"/>
Expand All @@ -428,13 +412,8 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Aditya Bakshi</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vaishnavipal1869">
<img src="https://avatars.githubusercontent.com/u/180996531?v=4" width="100;" alt="vaishnavipal1869"/>
<br />
<sub><b>vaishnavipal1869</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/tanishirai">
<img src="https://avatars.githubusercontent.com/u/178164785?v=4" width="100;" alt="tanishirai"/>
Expand All @@ -456,22 +435,13 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Sourabh Singh Rawat</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Shiva-Bajpai">
<img src="https://avatars.githubusercontent.com/u/141490705?v=4" width="100;" alt="Shiva-Bajpai"/>
<br />
<sub><b>Shiva Bajpai</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Pushpa472">
<img src="https://avatars.githubusercontent.com/u/116655535?v=4" width="100;" alt="Pushpa472"/>
<br />
<sub><b>Pushpa Vishwakarma </b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/devxMani">
<img src="https://avatars.githubusercontent.com/u/122438942?v=4" width="100;" alt="devxMani"/>
Expand All @@ -486,6 +456,8 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Ayush Yadav</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/smog-root">
<img src="https://avatars.githubusercontent.com/u/181578777?v=4" width="100;" alt="smog-root"/>
Expand All @@ -500,8 +472,6 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Vaibhav._Y</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Vaibhav-Kumar-K-R">
<img src="https://avatars.githubusercontent.com/u/132189791?v=4" width="100;" alt="Vaibhav-Kumar-K-R"/>
Expand Down Expand Up @@ -530,22 +500,15 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Sapna Kul</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Nikhil0-3">
<img src="https://avatars.githubusercontent.com/u/149102391?v=4" width="100;" alt="Nikhil0-3"/>
<br />
<sub><b>Nikhil More</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/MutiatBash">
<img src="https://avatars.githubusercontent.com/u/108807732?v=4" width="100;" alt="MutiatBash"/>
<br />
<sub><b>Bashua Mutiat</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Mohitranag18">
<img src="https://avatars.githubusercontent.com/u/152625405?v=4" width="100;" alt="Mohitranag18"/>
Expand All @@ -560,13 +523,6 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Jai Dhingra</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/harjasae2001">
<img src="https://avatars.githubusercontent.com/u/83627055?v=4" width="100;" alt="harjasae2001"/>
<br />
<sub><b>Harjas Singh</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mishradev1">
<img src="https://avatars.githubusercontent.com/u/118660840?v=4" width="100;" alt="mishradev1"/>
Expand Down
2 changes: 1 addition & 1 deletion backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MONGO_URI=enter_your_mongo_uri
MONGO_URI=
EMAIL_USER=your_gmail
PORT=3000
EMAIL_PASS=your_16_digit_pass
Expand Down
76 changes: 76 additions & 0 deletions backend/controller/order.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const Customer = require("../models/customer.model");
const Order = require("../models/order.model");

// Create a new order
exports.createOrder = async (req, res) => {
try {
const { items } = req.body;
const customerId = req.params.id.trim();

if (!customerId) {
return res
.status(400)
.json({ success: false, message: "Customer ID is required." });
}
Comment on lines +7 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate 'items' before calculating total amount

The items retrieved from req.body are not validated before use. If items is undefined or not an array, calling items.reduce() will throw a runtime error. Additionally, it's important to ensure that each item contains the necessary fields (price and quantity) for accurate total amount calculation.

Apply this diff to add validation for items:

  try {
    const { items } = req.body;
    const customerId = req.params.id.trim();

+   if (!items || !Array.isArray(items) || items.length === 0) {
+     return res
+       .status(400)
+       .json({ success: false, message: "Order items are required and should be a non-empty array." });
+   }
+
+   // Validate each item in the array
+   for (const item of items) {
+     if (!item.price || !item.quantity) {
+       return res
+         .status(400)
+         .json({ success: false, message: "Each item must have a price and quantity." });
+     }
+   }

    if (!customerId) {
      return res
        .status(400)
        .json({ success: false, message: "Customer ID is required." });
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { items } = req.body;
const customerId = req.params.id.trim();
if (!customerId) {
return res
.status(400)
.json({ success: false, message: "Customer ID is required." });
}
const { items } = req.body;
const customerId = req.params.id.trim();
if (!items || !Array.isArray(items) || items.length === 0) {
return res
.status(400)
.json({ success: false, message: "Order items are required and should be a non-empty array." });
}
// Validate each item in the array
for (const item of items) {
if (!item.price || !item.quantity) {
return res
.status(400)
.json({ success: false, message: "Each item must have a price and quantity." });
}
}
if (!customerId) {
return res
.status(400)
.json({ success: false, message: "Customer ID is required." });
}


const totalAmount = items.reduce(
(sum, item) => sum + item.price * item.quantity,
0
);
Comment on lines +16 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent price manipulation by fetching item prices from the database

Calculating totalAmount using item.price from the client request poses a security risk, as clients can manipulate item prices to reduce the total amount payable. Instead, you should fetch the actual prices from the database using item identifiers to ensure price integrity.

Would you like assistance in modifying the code to fetch item prices from the database for secure price calculations?


const order = new Order({
customer: customerId,
items,
totalAmount,
});

const savedOrder = await order.save();

await Customer.findByIdAndUpdate(customerId, {
$push: { orders: savedOrder._id },
});
Comment on lines +27 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Check if customer exists before updating orders

When adding a new order to a customer's record, the code assumes the customer exists. Attempting to update a non-existent customer will result in an error. It's important to verify the customer's existence before proceeding.

Apply this diff to check the customer's existence:

    const savedOrder = await order.save();

+   const customer = await Customer.findById(customerId);
+   if (!customer) {
+     // Optionally, you might want to rollback the order creation here
+     return res
+       .status(404)
+       .json({ success: false, message: "Customer not found." });
+   }

    await Customer.findByIdAndUpdate(customerId, {
      $push: { orders: savedOrder._id },
    });

Committable suggestion was skipped due to low confidence.


res.status(201).json({ success: true, order: savedOrder });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
Comment on lines +34 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid exposing internal error messages to clients

Returning error.message directly in the response may expose sensitive server information. It's better to send a generic error message to the client and log the detailed error on the server for debugging purposes.

Apply this diff to return a generic error message:

  } catch (error) {
-   res.status(500).json({ success: false, message: error.message });
+   console.error(error); // Log the detailed error message
+   res.status(500).json({ success: false, message: "An internal server error occurred." });
  }

Similar changes should be applied to the error handlers in the getOrders and deleteOrder functions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
} catch (error) {
console.error(error); // Log the detailed error message
res.status(500).json({ success: false, message: "An internal server error occurred." });
}

};

// Get all orders for a customer
exports.getOrders = async (req, res) => {
try {
const customerId = req.params.id.trim();

const orders = await Order.find({ customer: customerId });
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Check if the customer exists before retrieving orders

Currently, the code retrieves orders without verifying if the customer exists. If the customer ID is invalid or the customer does not exist, it may return an empty list or unexpected results. It's advisable to confirm the customer's existence first.

Apply this diff to check the customer's existence:

  try {
    const customerId = req.params.id.trim();

+   const customerExists = await Customer.exists({ _id: customerId });
+   if (!customerExists) {
+     return res
+       .status(404)
+       .json({ success: false, message: "Customer not found." });
+   }

    const orders = await Order.find({ customer: customerId });

Committable suggestion was skipped due to low confidence.

res.status(200).json({ success: true, orders });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};

// Delete an order
exports.deleteOrder = async (req, res) => {
try {
const { orderId } = req.body;
const customerId = req.params.id.trim();
Comment on lines +54 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Obtain orderId from URL parameters instead of request body

For consistency and following RESTful API conventions, it's better to pass the orderId as a URL parameter rather than in the request body for DELETE operations.

Apply this diff to adjust the code:

  try {
-   const { orderId } = req.body;
+   const orderId = req.params.orderId.trim();
    const customerId = req.params.id.trim();

Ensure that your route is updated to include :orderId as a parameter, like /delete/:customerId/:orderId.

Committable suggestion was skipped due to low confidence.


const order = await Order.findOne({ _id: orderId, customer: customerId });

if (!order) {
return res
.status(404)
.json({ success: false, message: "Order not found" });
}

await Order.deleteOne({ _id: orderId });
await Customer.findByIdAndUpdate(customerId, {
$pull: { orders: orderId },
});

res
.status(200)
.json({ success: true, message: "Order deleted successfully" });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
};
20 changes: 17 additions & 3 deletions backend/models/customer.model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-useless-escape */

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

Expand All @@ -19,16 +19,30 @@ const customerSchema = new Schema(
},
verificationCode: {
type: String,
default: ""
default: "",
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using null instead of empty string for verificationCode default.

Using an empty string as default makes it difficult to distinguish between unverified accounts and verified accounts where the code was cleared. Using null would make the verification state more explicit.

-      default: "",
+      default: null,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
default: "",
default: null,

role: {
type: String,
default: "customer",
},
bio: String,
profilePicture: String,

bookedEvents: [
{
type: Schema.Types.ObjectId,
ref: "Event",
},
],
orders: [
{
type: Schema.Types.ObjectId,
ref: "Order",
},
],

Comment on lines +31 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding indexes for frequently queried fields.

If you frequently query customers by their bookedEvents or orders, consider adding indexes to improve query performance.

    orders: [
      {
        type: Schema.Types.ObjectId,
        ref: "Order",
+       index: true
      },
    ],

Committable suggestion was skipped due to low confidence.


💡 Codebase verification

Add cascade delete hooks to handle orphaned references

The referenced models (Event and Order) exist in the codebase, but there's no mechanism to handle orphaned references when documents are deleted. To maintain data integrity:

  • Add pre('remove') hooks in the Event and Order models to clean up references in Customer documents
  • Or implement cascade delete logic in your controllers
  • Consider using mongoose-delete plugin for soft deletes if permanent deletion is not desired

Example implementation for Event model:

eventSchema.pre('remove', async function(next) {
  await mongoose.model('Customer').updateMany(
    { bookedEvents: this._id },
    { $pull: { bookedEvents: this._id } }
  );
  next();
});
🔗 Analysis chain

Verify referenced models and consider orphaned data handling.

Ensure that:

  1. The referenced models (Event and Order) exist in your codebase
  2. There's a strategy to handle orphaned references when Events or Orders are deleted

Let me check the cascade delete behavior in these models to complete the verification.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if referenced models exist
echo "Checking for Event model..."
rg -l "mongoose\.model\(.*Event.*\)" backend/models/

echo "Checking for Order model..."
rg -l "mongoose\.model\(.*Order.*\)" backend/models/

Length of output: 300


Script:

#!/bin/bash
# Check Event model implementation for cascade delete
echo "Event model implementation:"
cat backend/models/events.model.js

echo -e "\nOrder model implementation:"
cat backend/models/order.model.js

# Check if there are any pre/post delete hooks in the models
echo -e "\nChecking for delete hooks:"
rg "pre\('delete'" backend/models/
rg "post\('delete'" backend/models/

Length of output: 2116

},
{ timestamps: true },
{ timestamps: true }
);

const Customer = mongoose.model("Customer", customerSchema);
Expand Down
Loading
Loading