From 4559ccb9f599eb24cf228584e60f39fa6842d01e Mon Sep 17 00:00:00 2001 From: pawan-dot <71133473+pawan-dot@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:33:12 +0530 Subject: [PATCH] paypal integration --- .env | 3 +- app.js | 8 +- package-lock.json | 59 +- package.json | 1 + resources/Orders/orderController.js | 513 ++++++++++++------ resources/Orders/orderRoute.js | 44 +- .../ShippingAddressController.js | 298 ++++++++++ .../ShippingAddresses/ShippingAddressModel.js | 57 ++ .../ShippingAddresses/ShippingAddressRoute.js | 30 + resources/user/userModel.js | 110 ++-- 10 files changed, 870 insertions(+), 253 deletions(-) create mode 100644 resources/ShippingAddresses/ShippingAddressController.js create mode 100644 resources/ShippingAddresses/ShippingAddressModel.js create mode 100644 resources/ShippingAddresses/ShippingAddressRoute.js diff --git a/.env b/.env index 5488adf..6cd517e 100644 --- a/.env +++ b/.env @@ -21,4 +21,5 @@ SMPT_PORT="587" SMPT_MAIL="beameri.team@gmail.com" SMPT_PASSWORD="xsmtpsib-a88c224860249a3f1e0765e0e3d119c1bf07ad21f2859318fbf50975deee1711-JrdPpfsvF6LwEn4A" - +PAYPAL_CLIENT_ID="AemCjVuWswklp1sWUo4peCFg9eS4bofMsMR0RCrVRB2DifYR1IUSrWqtHpVmQlrVMKTI2cWZXLJAdYwn" +PAYPAL_CLIENT_SECRET="EAo0Y9ff3jpHHg1QAbftdebfh7cb_-vnebhQrP9KALbCVer908yx2tO2eHO39r7EJSfqc4D69Qgx8R31" \ No newline at end of file diff --git a/app.js b/app.js index 2e40539..9c07d14 100644 --- a/app.js +++ b/app.js @@ -51,6 +51,7 @@ import ConfigRouter from "./resources/setting/Configration/Config_routes.js"; import TaxRouter from "./resources/Tax/tax_routes.js"; //specialties import SpecialtiesRouter from "./resources/Specialties/SpecialtiesRoute.js"; +import ShippingAddressRoute from "./resources/ShippingAddresses/ShippingAddressRoute.js"; //short urls // import ShortUrlRouter from "./resources/Businesses/Short_Urls/ShortUrlRoute.js"; @@ -68,9 +69,9 @@ app.use("/api/category", categoryRoute); // Content app.use("/api/content", ContentRoute); // User Address -app.use("/api/user-address", UserAddressRoute); +app.use("/api/shipping/address", ShippingAddressRoute); //Order -app.use("/api", orderRoute); +app.use("/api/order", orderRoute); //Departure app.use("/api/departure/", DepartureRouter); //Information @@ -85,8 +86,7 @@ app.use("/api/state", StateRouter); app.use("/api/language", LanguageRoute); //Purpose app.use("/api/purpose", PurposeRoute); -//Business_Type -// app.use("/api/business", Business_TypeRoute); +app.use("/api/business", orderRoute); //Tax app.use("/api/tax", TaxRouter); //config diff --git a/package-lock.json b/package-lock.json index a884a6e..1afcf6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@sendgrid/mail": "^7.7.0", + "axios": "^1.6.2", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cloudinary": "^1.30.0", @@ -42,6 +43,14 @@ "node": "6.* || 8.* || >=10.*" } }, + "node_modules/@sendgrid/client/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/@sendgrid/helpers": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.7.0.tgz", @@ -200,12 +209,19 @@ "node": ">=4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dependencies": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/balanced-match": { @@ -414,6 +430,17 @@ "lodash": ">=4.0" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -591,6 +618,14 @@ "node": ">= 6" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/denque": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", @@ -825,6 +860,19 @@ } } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1816,8 +1864,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "optional": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pstree.remy": { "version": "1.1.8", diff --git a/package.json b/package.json index be65ee7..9379766 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "license": "ISC", "dependencies": { "@sendgrid/mail": "^7.7.0", + "axios": "^1.6.2", "bcryptjs": "^2.4.3", "body-parser": "^1.20.0", "cloudinary": "^1.30.0", diff --git a/resources/Orders/orderController.js b/resources/Orders/orderController.js index 46c310e..0de56a7 100644 --- a/resources/Orders/orderController.js +++ b/resources/Orders/orderController.js @@ -1,201 +1,362 @@ -import { Order } from './orderModel.js' +import { Order } from "./orderModel.js"; import { generate } from "generate-password"; +const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET } = process.env; +const base = "https://api-m.sandbox.paypal.com"; +import axios from "axios"; + +export const getClientId = async (req, res) => { + try { + res.status(200).json({ + success: true, + clientId: PAYPAL_CLIENT_ID, + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; export const createOrder = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - // console.log(req?.user) - let isUnique = false; - let order_id = generate({ - length: 9, - numbers: true, - lowercase: false, - uppercase: false, - }); - - while (!isUnique) { - const unqOrder = await Order.findOne({ order_id }); - if (!unqOrder) { - isUnique = true; - } else { - order_id = generate({ - length: 9, - numbers: true, - lowercase: false, - uppercase: false, - }); - } - } - - req.body.user = req.user._id - req.body.order_id = order_id - const order = await Order.create(req.body); - - res.status(201).json({ - success: true, - order, - message: 'order Created', - }); - - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : 'Something went Wrong', + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + let isUnique = false; + let order_id = generate({ + length: 9, + numbers: true, + lowercase: false, + uppercase: false, + }); + + while (!isUnique) { + const unqOrder = await Order.findOne({ order_id }); + if (!unqOrder) { + isUnique = true; + } else { + order_id = generate({ + length: 9, + numbers: true, + lowercase: false, + uppercase: false, }); + } } -} + req.body.user = req.user._id; + req.body.order_id = order_id; + const order = await Order.create(req.body); + + res.status(201).json({ + success: true, + order, + message: "order Created", + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; export const getAllOrder = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - // console.log(req?.user) + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) - - const order = await Order.find().populate({ - path: "user", - select: "name -_id", - }).sort({ createdAt: -1 }); - if (order) { - res.status(201).json({ - success: true, - order, - message: 'All Order Fetched', - }); - } - - - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : 'Something went Wrong', - }); + const order = await Order.find() + .populate({ + path: "user", + select: "name -_id", + }) + .sort({ createdAt: -1 }); + if (order) { + res.status(201).json({ + success: true, + order, + message: "All Order Fetched", + }); } - -} + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; export const getSingleOrder = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - // console.log(req?.user) - if (!req.params.id) return res.status(400).json({ message: "please Provide Order Id" }); + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + if (!req.params.id) + return res.status(400).json({ message: "please Provide Order Id" }); + const order = await Order.findById(req.params.id) + .populate({ + path: "user", + select: "name -_id", + }) + .populate({ + path: "shippingInfo", - - const order = await Order.findById(req.params.id).populate({ - path: "user", - select: "name -_id", - - - }).populate({ - path: "shippingInfo", - - populate: { - path: "Franchisee", - select: "banner price_Lable ", - }, - }).sort({ createdAt: -1 }); - if (order) { - res.status(201).json({ - success: true, - order, - message: ' Order Fetched', - }); - } - - - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : 'Something went Wrong', - }); - + populate: { + path: "Franchisee", + select: "banner price_Lable ", + }, + }) + .sort({ createdAt: -1 }); + if (order) { + res.status(201).json({ + success: true, + order, + message: " Order Fetched", + }); } - -} + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; export const EditOrderBeforePayment = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - // console.log(req?.user) - if (!req.params.id) return res.status(400).json({ message: "please Provide Order Id" }); + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + if (!req.params.id) + return res.status(400).json({ message: "please Provide Order Id" }); + const order = await Order.findById(req.params.id); + if (order) { + if (order.isPaid === false) { + if (order.user.toString() === req.user._id.toString()) { + req.body.user = req.user._id; + const ModifyOrder = await Order.findByIdAndUpdate( + req.params.id, + req.body, - const order = await Order.findById(req.params.id) - if (order) { - if (order.isPaid === false) { - - - - if (order.user.toString() === req.user._id.toString()) { - req.body.user = req.user._id - - const ModifyOrder = await Order.findByIdAndUpdate(req.params.id, req.body, - - { - new: true, - runValidators: true, - useFindAndModify: false, - } - - ); - res.status(200).json({ - success: true, - order: ModifyOrder, - message: ' Order Updated', - }); - } - else { - return res.status(400).json({ message: 'You not created This So You Can not Edit this Order !! ' }) - - } - - + { + new: true, + runValidators: true, + useFindAndModify: false, } - else { - return res.status(400).json({ message: 'order can not Edited Because Payment Done !! ' }) - - } - - } - - - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : 'Something went Wrong', - }); - } - -} -export const deleteOneOrder = async (req, res) => { - try { - if (!req?.user) return res.status(400).json({ message: "please login !" }); - if (!req.params.id) return res.status(400).json({ message: "please Provide Order Id" }); - const getOrder = await Order.findById(req.params.id); - if (!getOrder) { - return res.status(404).json({ - success: false, - message: "No Order Found!" - }); - - } - const order = await Order.findByIdAndDelete(req.params.id) - - await order.remove(); - res.status(200).json({ + ); + res.status(200).json({ success: true, - message: "Order Deleted Successfully!!", - - }); - - } catch (error) { - res.status(500).json({ - success: false, - message: error.message ? error.message : 'Something went Wrong', - }); + order: ModifyOrder, + message: " Order Updated", + }); + } else { + return res.status(400).json({ + message: "You not created This So You Can not Edit this Order !! ", + }); + } + } else { + return res + .status(400) + .json({ message: "order can not Edited Because Payment Done !! " }); + } } + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; +export const deleteOneOrder = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + if (!req.params.id) + return res.status(400).json({ message: "please Provide Order Id" }); + const getOrder = await Order.findById(req.params.id); + if (!getOrder) { + return res.status(404).json({ + success: false, + message: "No Order Found!", + }); + } + const order = await Order.findByIdAndDelete(req.params.id); -} + await order.remove(); + res.status(200).json({ + success: true, + message: "Order Deleted Successfully!!", + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; +// parse post params sent in body in json format +/** + * Generate an OAuth 2.0 access token for authenticating with PayPal REST APIs. +// https://developer.paypal.com/api/rest/authentication/ + */ +const generateAccessToken = async () => { + const credentials = `${PAYPAL_CLIENT_ID}:${PAYPAL_CLIENT_SECRET}`; + const base64Credentials = Buffer.from(credentials).toString("base64"); + + const headers = { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: `Basic ${base64Credentials}`, + }; + + const data = "grant_type=client_credentials"; + + try { + const response = await axios.post( + "https://api.sandbox.paypal.com/v1/oauth2/token", + data, + { + headers: headers, + } + ); + // console.log("response.data", response.data); + const accessToken = response.data?.access_token; + return accessToken; + // console.log("Access Token:", accessToken); + } catch (error) { + console.error( + "Error getting access token:", + error.response ? error.response.data : error.message + ); + } +}; +// } catch (error) { +// console.error("Failed to generate Access Token:"); +// } +// }; + +const handleResponse = async (response) => { + try { + if (response.status >= 200 && response.status < 300) { + return { + success: true, + responseData: response.data, + httpStatusCode: response.status, + }; + } + } catch (err) { + const errorMessage = await response.statusText; + throw new Error(errorMessage); + } +}; + +// https://developer.paypal.com/docs/api/orders/v2/#orders_create + +export const createOrderCheckout = async (rea, res) => { + try { + // const { cart } = req.body; + // use the cart information passed from the front-end to calculate the purchase unit details + // console.log( + // "shopping cart information passed from the frontend createOrder() callback:", + // cart + // ); + const accessToken = await generateAccessToken(); + const url = `https://api.sandbox.paypal.com/v2/checkout/orders`; + const createOrderRequest = { + intent: "CAPTURE", + purchase_units: [ + { + amount: { + currency_code: "USD", + value: "60.00", // Replace with the actual amount + breakdown: { + item_total: { + currency_code: "USD", + value: "60.00", // Replace with the total value of all items + }, + }, + }, + items: [ + { + name: "Apple", + unit_amount: { + currency_code: "USD", + value: "60.00", // Replace with the actual item price + }, + quantity: 1, + }, + ], + }, + ], + }; + const response = await axios.post(url, JSON.stringify(createOrderRequest), { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, + }, + }); + + if (response.status >= 200 && response.status < 300) { + return res.status(201).json({ + success: true, + responseData: response.data, + httpStatusCode: response.status, + }); + } else { + // Handle errors or unexpected status codes + console.error("Error:", response.status, response.statusText); + + // Optionally, you can parse the error response as JSON if available + try { + const errorData = response.data; + console.error("Error Data:", errorData); + } catch (error) { + console.error("Error parsing error data:", error.message); + } + } + } catch (error) { + const errorMessage = await response.statusText; + return res.status(500).json({ + success: false, + message: errorMessage, + }); + } +}; + +/** + * Capture payment for the created order to complete the transaction. + * //see https://developer.paypal.com/docs/api/orders/v2/#orders_capture + */ + +const captureOrder = async (orderID) => { + const accessToken = await generateAccessToken(); + const url = `${base}/v2/checkout/orders/${orderID}/capture`; + const response = await axios.post( + url, + {}, + { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, + // Uncomment one of these to force an error for negative testing (in sandbox mode only). Documentation: + // https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/ + // "PayPal-Mock-Response": '{"mock_application_codes": "INSTRUMENT_DECLINED"}' + // "PayPal-Mock-Response": '{"mock_application_codes": "TRANSACTION_REFUSED"}' + // "PayPal-Mock-Response": '{"mock_application_codes": "INTERNAL_SERVER_ERROR"}' + }, + } + ); + return handleResponse(response); +}; + +export const captureOrderPayment = async (req, res) => { + try { + const { orderID } = req.params; + const { responseData, httpStatusCode } = await captureOrder(orderID); + return res.status(httpStatusCode).json(responseData); + } catch (error) { + console.error("Failed to create order:", error); + res.status(500).json({ error: "Failed to capture order." }); + } +}; diff --git a/resources/Orders/orderRoute.js b/resources/Orders/orderRoute.js index c341e71..d0bfc69 100644 --- a/resources/Orders/orderRoute.js +++ b/resources/Orders/orderRoute.js @@ -1,19 +1,39 @@ -import { createOrder, deleteOneOrder, EditOrderBeforePayment, getAllOrder, getSingleOrder } from "./orderController.js"; +import { + captureOrderPayment, + createOrder, + createOrderCheckout, + deleteOneOrder, + EditOrderBeforePayment, + getAllOrder, + getSingleOrder, + getClientId, +} from "./orderController.js"; import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js"; -import express from 'express' -const router = express.Router() - -router.route("/order/create").post(isAuthenticatedUser, authorizeRoles("admin"), createOrder) -router.route("/order/getAll").get(isAuthenticatedUser, authorizeRoles("admin"), getAllOrder) -router.route("/order/getOne/:id").get(isAuthenticatedUser, authorizeRoles("admin"), getSingleOrder) -router.route("/order/edit/:id").put(isAuthenticatedUser, authorizeRoles("admin"), EditOrderBeforePayment) - - -router.route("/order/delete/:id").delete(isAuthenticatedUser, authorizeRoles("admin"), deleteOneOrder) +import express from "express"; +const router = express.Router(); +router.route("/checkout/").post(createOrderCheckout); +router.route("/clientid/get/").get(getClientId); +router.route("/:orderID/capture/payment").post(captureOrderPayment); +// .capturePayment(orderID) +router + .route("/order/create") + .post(isAuthenticatedUser, authorizeRoles("admin"), createOrder); +router + .route("/order/getAll") + .get(isAuthenticatedUser, authorizeRoles("admin"), getAllOrder); +router + .route("/order/getOne/:id") + .get(isAuthenticatedUser, authorizeRoles("admin"), getSingleOrder); +router + .route("/order/edit/:id") + .put(isAuthenticatedUser, authorizeRoles("admin"), EditOrderBeforePayment); +router + .route("/order/delete/:id") + .delete(isAuthenticatedUser, authorizeRoles("admin"), deleteOneOrder); // router.route("/product/getAll/").get(getAllProduct) -export default router \ No newline at end of file +export default router; diff --git a/resources/ShippingAddresses/ShippingAddressController.js b/resources/ShippingAddresses/ShippingAddressController.js new file mode 100644 index 0000000..c217358 --- /dev/null +++ b/resources/ShippingAddresses/ShippingAddressController.js @@ -0,0 +1,298 @@ +import { shippingAddress } from "./ShippingAddressModel.js"; +import { generate } from "generate-password"; + +export const AddshippingAddress = async (req, res) => { + try { + const { + first_Name, + last_Name, + phone_Number, + street, + city, + state, + postalCode, + country, + } = req.body; + console.log("hiiii"); + switch (true) { + //validation + case !first_Name: { + return res.status(404).json({ msg: "please provide first_Name" }); + } + case !last_Name: { + return res.status(404).json({ msg: "please provide last_Name" }); + } + case !phone_Number: { + return res.status(404).json({ msg: "please provide phone_Number" }); + } + case !street: { + return res.status(404).json({ msg: "please provide street" }); + } + case !city: { + return res.status(404).json({ msg: "please provide city" }); + } + case !state: { + return res.status(404).json({ msg: "please provide state" }); + } + case !postalCode: { + return res.status(404).json({ msg: "please provide postalCode" }); + } + case !country: { + return res.status(404).json({ msg: "please provide country" }); + } + } + + // let isUnique = false; + // let Machine_ID = generate({ + // length: 8, + // numbers: true, + // lowercase: false, + // uppercase: false, + // }); + // let Tablet_ID = generate({ + // length: 8, + // numbers: true, + // lowercase: false, + // uppercase: false, + // }); + + // while (!isUnique) { + // const unqmachine = await shippingAddress.findOne({ Machine_ID }); + // if (!unqmachine) { + // isUnique = true; + // console.log(unqmachine); + // } else { + // Machine_ID = generate({ + // length: 8, + // numbers: true, + // lowercase: false, + // uppercase: false, + // }); + // Tablet_ID = generate({ + // length: 8, + // numbers: true, + // lowercase: false, + // uppercase: false, + // }); + // } + // } + + req.body.user = req.user._id; + // req.body.Machine_ID = Machine_ID; + // req.body.Tablet_ID = Tablet_ID; + + const address = await shippingAddress.create(req.body); + + res.status(201).json({ + success: true, + address, + message: "shipping Address Added", + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; + +export const getAllmachine = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + + const machine = await shippingAddress + .find() + .populate({ + path: "user", + select: "name -_id", + }) + .populate({ + path: "Allocated_To", + select: "name _id", + }) + .sort({ createdAt: -1 }); + if (machine) { + res.status(201).json({ + success: true, + machine, + message: "All machine Fetched", + }); + } + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; +export const getSinglemachine = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + if (!req.params.id) + return res.status(400).json({ message: "please Provide machine Id" }); + + const machine = await shippingAddress + .findById(req.params.id) + .populate({ + path: "user", + select: "name -_id", + }) + .populate({ + path: "Allocated_To", + select: "name _id", + }); + if (machine) { + res.status(201).json({ + success: true, + machine, + message: " machine Fetched", + }); + } + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; +export const EditMachine = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + + const { Allocated_To, Allocated_On } = req.body; + switch (true) { + //validation + + case !Allocated_To: { + return res.status(404).json({ msg: "please provide Allocated To" }); + } + case !Allocated_On: { + return res.status(404).json({ msg: "please provide AllocatedOn Date" }); + } + } + + const machine = await shippingAddress.findById(req.params.id); + if (machine) { + const Modifymachine = await shippingAddress.findByIdAndUpdate( + req.params.id, + req.body, + + { + new: true, + runValidators: true, + useFindAndModify: false, + } + ); + res.status(200).json({ + success: true, + machine: Modifymachine, + message: " shippingAddress Updated", + }); + } + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; + +// + +//varification +export const machineVarificationFromAdmin = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + // console.log(req?.user) + if (!req.params.id) + return res.status(400).json({ message: "please Provide machine Id" }); + const getMachine = await shippingAddress.findById(req.params.id); + if (getMachine) { + if (req.user.role === "admin") { + if (getMachine.Status === false) { + getMachine.Status = true; + } else { + getMachine.Status = false; + } + + getMachine.save(); + + return res.status(200).json({ + success: true, + message: `shippingAddress status change successfully`, + }); + } + } else { + return res.status(400).json({ message: "Only Admin Change Status" }); + } + } catch (err) { + // console.log(err) + return res + .status(500) + .json({ message: err.message ? err.message : "Something went wrong." }); + } +}; + +//get machine using franchisee id + +export const getMachineDetails = async (req, res) => { + try { + if (!req?.franchi) + return res.status(400).json({ message: "please login !" }); + + const machine = await shippingAddress + .find({ + Allocated_To: req.franchi._id, + Status: true, + }) + .populate({ + path: "Allocated_To", + select: "name _id", + }); + if (machine) { + res.status(201).json({ + success: true, + machine, + message: " machine Fetched", + }); + } + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; + +/// +export const deleteOneMachine = async (req, res) => { + try { + if (!req?.user) return res.status(400).json({ message: "please login !" }); + if (!req.params.id) + return res + .status(400) + .json({ message: "please Provide shippingAddress Id" }); + const getmachine = await shippingAddress.findById(req.params.id); + if (!getmachine) { + return res.status(404).json({ + success: false, + message: "No shippingAddress Found!", + }); + } + const machine = await shippingAddress.findByIdAndDelete(req.params.id); + + await machine.remove(); + res.status(200).json({ + success: true, + message: "shippingAddress Deleted Successfully!!", + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message ? error.message : "Something went Wrong", + }); + } +}; diff --git a/resources/ShippingAddresses/ShippingAddressModel.js b/resources/ShippingAddresses/ShippingAddressModel.js new file mode 100644 index 0000000..d2f4f5a --- /dev/null +++ b/resources/ShippingAddresses/ShippingAddressModel.js @@ -0,0 +1,57 @@ +import mongoose from "mongoose"; +const shippingAddressSchema = new mongoose.Schema( + { + first_Name: { + type: String, + required: true, + }, + last_Name: { + type: String, + required: true, + }, + phone_Number: { + type: Number, + required: true, + }, + street: { + type: String, + required: true, + }, + city: { + type: String, + required: true, + trim: true, + }, + state: { + type: String, + required: true, + }, + postalCode: { + type: String, + required: true, + trim: true, + // Add a regular expression to enforce a specific postal code format + // For example, assuming a 5-digit format for the United States + match: /^\d{5}$/, + }, + country: { + type: String, + required: true, + }, + default: { + type: Boolean, + default: false, + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + }, + { timestamps: true, versionKey: false } +); + +export const shippingAddress = mongoose.model( + "ShippingAddress", + shippingAddressSchema +); diff --git a/resources/ShippingAddresses/ShippingAddressRoute.js b/resources/ShippingAddresses/ShippingAddressRoute.js new file mode 100644 index 0000000..dc300b2 --- /dev/null +++ b/resources/ShippingAddresses/ShippingAddressRoute.js @@ -0,0 +1,30 @@ +import express from "express"; +import { AddshippingAddress } from "./ShippingAddressController.js"; +import { isAuthenticatedUser } from "../../middlewares/auth.js"; +const router = express.Router(); + +router.route("/new").post(isAuthenticatedUser, AddshippingAddress); +// router +// .route("/getAll") +// .get(isAuthenticatedUser, getAllmachine); +// router +// .route("/getOne/:id") +// .get(isAuthenticatedUser, getSinglemachine); +// router +// .route("/edit/:id") +// .put(isAuthenticatedUser, EditMachine); + +// router +// .route("/delete/:id") +// .delete(isAuthenticatedUser, deleteOneMachine); +// router +// .route("/admin/verify/:id") +// .get( +// isAuthenticatedUser, +// authorizeRoles("admin"), +// machineVarificationFromAdmin +// ); + +// + +export default router; diff --git a/resources/user/userModel.js b/resources/user/userModel.js index 35a3fd9..ab83174 100644 --- a/resources/user/userModel.js +++ b/resources/user/userModel.js @@ -1,49 +1,50 @@ -import dotenv from 'dotenv' -dotenv.config() -import mongoose from "mongoose" -import validator from "validator" -import bcrypt from "bcryptjs" -import jwt from "jsonwebtoken" -import crypto from "crypto" +import dotenv from "dotenv"; +dotenv.config(); +import mongoose from "mongoose"; +import validator from "validator"; +import bcrypt from "bcryptjs"; +import jwt from "jsonwebtoken"; +import crypto from "crypto"; -const userSchema = new mongoose.Schema({ +const userSchema = new mongoose.Schema( + { name: { - type: String, - required: [true, "Please Enter Your Name"], - maxLength: [30, "Name cannot exceed 30 characters"], - minLength: [4, "Name should have more than 4 characters"], + type: String, + required: [true, "Please Enter Your Name"], + maxLength: [30, "Name cannot exceed 30 characters"], + minLength: [4, "Name should have more than 4 characters"], }, email: { - type: String, - required: [true, "Please Enter Your Email"], - unique: true, - validate: [validator.isEmail, "Please Enter a valid Email"], + type: String, + required: [true, "Please Enter Your Email"], + unique: true, + validate: [validator.isEmail, "Please Enter a valid Email"], }, phone: { - type: Number, - // required: [true, "Please Enter Your phone no."], - maxLength: [12, "phone cannot exceed 12 characters"], - minLength: [6, "phone should have more than 6 characters"], + type: Number, + // required: [true, "Please Enter Your phone no."], + maxLength: [12, "phone cannot exceed 12 characters"], + minLength: [6, "phone should have more than 6 characters"], }, password: { - type: String, - required: [true, "Please Enter Your Password"], - minLength: [6, "Password should be greater than 6 characters"], - select: false,//find not got passpord + type: String, + required: [true, "Please Enter Your Password"], + minLength: [6, "Password should be greater than 6 characters"], + select: false, //find not got passpord }, avatar: { - public_id: { - type: String, - // required: true, - }, - url: { - type: String, - // required: true, - }, + public_id: { + type: String, + // required: true, + }, + url: { + type: String, + // required: true, + }, }, role: { - type: String, - default: "user", + type: String, + default: "user", }, // createdAt: { // type: Date, @@ -52,44 +53,45 @@ const userSchema = new mongoose.Schema({ resetPasswordToken: String, resetPasswordExpire: Date, -}, { timestamps: true }); + }, + { timestamps: true } +); userSchema.pre("save", async function (next) { - if (!this.isModified("password")) { - next(); - } + if (!this.isModified("password")) { + next(); + } - this.password = await bcrypt.hash(this.password, 10); + this.password = await bcrypt.hash(this.password, 10); }); // JWT TOKEN userSchema.methods.getJWTToken = function () { - return jwt.sign({ id: this._id }, process.env.JWT_SECRET); + return jwt.sign({ id: this._id }, process.env.JWT_SECRET); }; - // Compare Password userSchema.methods.comparePassword = async function (password) { - return await bcrypt.compare(password, this.password); + return await bcrypt.compare(password, this.password); }; // Generating Reset Token userSchema.methods.getResetPasswordToken = function () { - // Generating Token - const resetToken = crypto.randomBytes(20).toString("hex"); + // Generating Token + const resetToken = crypto.randomBytes(20).toString("hex"); - // Hashing and adding reset PasswordToken to userSchema - this.resetPasswordToken = crypto - .createHash("sha256") - .update(resetToken) - .digest("hex"); - //expire password time - // console.log(this.resetPasswordToken) - this.resetPasswordExpire = Date.now() + 15 * 60 * 1000;//15 minut + // Hashing and adding reset PasswordToken to userSchema + this.resetPasswordToken = crypto + .createHash("sha256") + .update(resetToken) + .digest("hex"); + //expire password time + // console.log(this.resetPasswordToken) + this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; //15 minut - return resetToken; + return resetToken; }; const UserModel = mongoose.model("User", userSchema); -export default UserModel; \ No newline at end of file +export default UserModel;