From 059e39e13cdc0360b4497ffff48df229fae96e84 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 27 Aug 2024 13:00:55 +0530 Subject: [PATCH] task updated and product manual completed --- app.js | 3 + public/uploads/Add-PD.xlsx | Bin 12143 -> 12381 bytes .../ProductMannual/ProductManualController.js | 181 ++++++++++++++++++ .../ProductMannual/ProductManualModel.js | 25 +++ .../ProductMannual/ProductManualRoute.js | 90 +++++++++ resources/Task/TaskController.js | 27 +++ resources/Task/TaskModel.js | 10 +- resources/Task/TaskRoute.js | 7 +- resources/user/userController.js | 14 +- 9 files changed, 353 insertions(+), 4 deletions(-) create mode 100644 resources/ProductMannual/ProductManualController.js create mode 100644 resources/ProductMannual/ProductManualModel.js create mode 100644 resources/ProductMannual/ProductManualRoute.js diff --git a/app.js b/app.js index 3b306e0..63a657f 100644 --- a/app.js +++ b/app.js @@ -132,6 +132,7 @@ app.use( //auth import user from "./resources/user/userRoute.js"; import ProductRouter from "./resources/Products/ProductRoute.js"; +import ProductManualRouter from "./resources/ProductMannual/ProductManualRoute.js"; //Businesses // import BusinessRoute from "./resources/Businesses/BusinessRoute.js"; @@ -199,6 +200,8 @@ app.use("/api/v1", user); //Product app.use("/api", ProductRouter); +//Product Manual +app.use("/api/productmanual", ProductManualRouter); //businesses // app.use("/api/businesses", BusinessRoute); // Design diff --git a/public/uploads/Add-PD.xlsx b/public/uploads/Add-PD.xlsx index b7a1ef1cd98b60f326ba2105fb9dd7756cf844bd..21ce549b82252e3d85a00717a95fb17a4052e995 100644 GIT binary patch delta 4608 zcmYjVWmFVw(_VI2SW<*#0bQDloaWbSh^9E zl9KM%=Y7xlp6~uKXU>`UF>_|-y6!#81*@tF0{lxO4PxvJ0X=$DdrlA1;2q1eO&3BjDI@BvgQ{1+0=R1)sfI^Gw=r6aUu8s8y$3p(j5L*G-_vF##=|roDD}0&myj!DZa&lmG`$L9$3e5(JR1?qTiv{;ai+ z*ihFipPSv<9$n$B&eyyZ?#4ajh$8NG;kpup*tF%F|9~-%?zKNTlp3B^w)g4FcU2Un z8V3gI?e}{-+Mh6dPS~=y@K5FDd7a|XzM}`i=%gZONJ>OAiQ-$>18XPuqgNgS9lxPC zjHRbb*HR5thj#8NT=H##uG#j9{NINhTazzFK+n_U(4Iyed_45%c!TCHjGqQb?iq2>)ContgEHT~|fn{G_ zPwc-KA*qs|ojupc%NTOv`%OmsB{TwiSJj%f2`Si}TBW7wJY%d*@?d`B;^X?g-yS(% zS2k!a_0V2J%T~c{3Ou!2F>&q^|CrFUun{vHc9BV65cOU-1S=P_OKNG&tS+i-Ggb}rm|fg;)06^K;ukU7mfP{A`- zmyF3g@Y#?oIHOKhAFwBmTTe4GzmgLkDj>>FW9aMNnA&AQxXU!PsteG{cm!-jXGn?> za*w(@xaL_m$CBUDEzCu~IS_B0GS16O)OpvQ<6)u15_4fUt?d0Ya`Y(x+fD$jsU&&` zBz7?J`T~Uj0KE*@OAuu1_LdclxeRFdfOn>^mgGY@Oct{AW68f6m!!jSOr1zkbDB>xzs`D2duD*F+s1lT zrV=bY4%P?P7uQV_I_a6^VeSw}?2yM#^Yptm{s?GIFiHi)Qy`AUNWBm>voT{eUQsD! z*P$&`7MfWmVHVM&ZRADJ+)3Me?>G;(Q67S?x$(@*1{a<|Gi;tUxH*`Y!6@#VX!@Nz ziGdD(sE-wQ(NkLBNE3XkP4FF3@uKSBP(oY7Gq0TA0$}IacV2&mFrn;g>I&itksMIvkOfAgT7yjeajjj!skFzAgG z?qPI1N$pPgXw(`Uq~TF3u=~z7-7Ob3Pb8Q_>vR2O^yO5`8NMDfQ#m?ENqBcn@fFl( z;T^NwWtrarY;CLBGWIldDQ|C6fPgyJ?s7J8qUZ5L6b~V~TRmQ(+@i*=>s-;8+=BR5 zaF3@22&9^Ccltb(-L^=x{*$}G+dR(f72(!&+s@NTr{hYJiDc zSo&w^H+04@n(9Z216<8o>o$|~K<1nV0Jyyc{38-m=1_Bjq;H-U^n!S$jq648@t(;< z*Vq~K`#R=Hz#mE zrv|peZ!SxRwl?FwTWUXTyDcA1#+@Hu`xmrMPoRChF!f8h2ZxxC8>b}K7u7z_H8<0! z$)YlK{~k6ZmRk%jTDtDFlW$3QQq6BY5>`I)lJNJiN6zomqgONC3sllg*T!-+`G}oH zi(og;s@a*{oD)QED+@)eYi8yls=GlYs--B-h_zK4m8|nRw^@CFhEG6 z6y0t8CWNRbo8>M19;Aet;?Gi)6tmv7Sc*B17;_HBBA1x%@dEhZJsdV|1h>)N-T)N? z>zbnjZ>q(*e@%XtRmcdq@h977VuHS4Wm-GoWQtrMh9vj^9|~Uxr6}a25SH3$>NBsZ zQzOm$aw1GCB}D<-8=?ALx!g0w7_To)=pxLSY$*#nj^bEzpl=x6y zmCEz*39LaGCj7xJxSw0Gw&=}Ws%(5!cNVM+QA!k=T6Ymee#Uk;%F4>^d_P>nI0-s*~<@eeBYI~=iu{xQi6 z4+XC>{ZciMtQ|qBky9CTA~_3C4((gND>Qcd7+0V?z<}5LG6CYonWlG#r~U$55VLu%-8K+$4@9syj5elQ?el^#M@iGjQs9jrvVYuGZ}I;LmWil2bv# zwF?04*bG2BO+Bn~Uy49=HI&qd9>y&(Qdz0*l5rF=`f%hJtbDmS6AXqjMYRr1( z;Cll7@s)v@CcO3GY;U!?Go6W?&c$wKn5v;d%bdwbPg|2nqts4>tvr3}t9uenE0POx zE;0+Qg-?ru=IA42;ccg@=YsI2vbpq@-*1N_R&oB-i!s-zIqEI()nmn0hCPO=xhr@j zx~)aO&F7PtuKQ~weg-gDVCZ!LCXKRbt0T+rO#X@PVD_>IQj7U)IvYPdIFO$LZpw+c zbR3l#wx?bLbDn_*HE4)QySdaIeZmyd6zDoKnmMTExgBAD!)VR=iW7n}YQX&5N}?rw zUw$4tGVeY^rM6(O$v7#f5}{2+7)algflqEuF_p?g_~r+6}D1LN9PHW6n1kC98C3dEY- z1vK{|aBC(A)k=aE!RELlotZH~PRa!tU0aG`&z8+8bXlS}X-3yzb#={XehrzYreJexQnP?!iaihe) z4o(K;8RvLdGSP`!_2b#}lLO6I15I=cUOw`#%h_S|xXK)_6l9Xe zT{awxW?1?a7|7qjiN2x_EIYZrR+4Ykr*xJe#hEeR#+Na6oOv&vUVC5C{1-K>P_d8` z*YXK#yaxdQ1f*Cp7C7204kt|!Bu{zU-cPk|J=eKlr#H@*Ps8~eRpR*W$r5|4`WTz` z+a178rMxeUt@kr^;I>5SrNnA#^Nr5?wfj`UmFF$1WabfqLB-gNqSNo|3v=ls%({4w zvp-5T`DtrOR~8A}q#{cqCx8A~>`QdEB#ZbHUroH0jiQ}OsH{U5D{Qv0(D$nfBJH|U zO8c387OadFztejbn^n{}w_Vl>BJ4~eRn}%x zVj$fmoWcr}_uY<0iS&CD$nrf8<~#s|goXgch%lcd3DC0>#|dvQe?ZUfQar|oYCTIn z#8hJjsjuh{HqK#nN=B9(leNWvsO^kcxk!Qrfmv@WJTpI7B)$l60cYzZia(*s=%i>k z>8twQIr+??KH!@*#7^8*B_Ldn{pZM??#S50kn_|{f|ukM72+g+f)p)VseM%HM}Ix- zOq@#xTU?+QEjCP)58btB7HytUfl>MP#brk)?A|?#!k;j(fu<(2sk-wEuH1S^R^7DIvh*vCqj1~89Et$9$E>q}Lt^Rp_;K+>LeQS$xlPV3>DNx$uedV<B)Aa1*Kzx?vu0}~fI)!}DeB2NSS+SItedJXJ~2gDeE zwpv8PK8;G307T_}*}OvBm)y|Q%?eA1avMy2;4=(R1mRlrlC>V)%KAOIJ)#cyEzUJd z_m_r%e(3ZkI!8%aAA%AcU*_#>b(rq`qiLI3MhpDO80U4^@sAL zWSVFieTpB<0{O=(`a-QXEci0(^HV^vvjpBW+L?DaiXW5cy7`9-iqWrx?+tyvEN@RD zOzSEvNtqKBy7jFRI$WBqo$I^DSiCEi=FSGD(dpxIYUCuY=z1bVrVCEPS~ff#_{4rq z^{SBlSKvIMHvx3D2e0xF@RE*+`at}S&0Nz1Y7g1I4oC-J@|(0NTwO;d@q_-Y>l$wM zL)4VwC!wA%$}#7Y_dy_UdsbKHTL*tDF~||iOn$0HX#iGs8z&p?J(8){dp5ZCd1Cb_ zL(v~gsQVg=Gb!cR^D_8zEgyEZY*uxJ|IZS{=c^f)tm$Ou!b5)(goZCYy1Jve)PMrr zO><>)enDyb1Jd0vYng5RJh@)-WN$}2g(7gjT5df^ZoRPY${4mtYhql2r8ptuVmLM+$| z$$?7bFY!@pL3dHx2Q-4=5i9t~R$N6%KVTb1pu3sz8Dza%+0o=*>D~Y};wP6mBlqK` zLimTWK$)H^yy33gQ=8D!gdr0F^4+|F$#s1gY`{5(})!E(r3#}5sGbL^ipr7!=!$1K>pEHG^JU*z!bXaE4L|9bq@VC-0P1OhwHPx0SA bWB2)Cz-$gIL_iM6&5czPU?JGz{U_i*6`P-$ delta 4389 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 { + const { title } = req.body; + + try { + let productManualDetails; + + // Check if a file is provided + if (req.files && req.files.product_manual) { + const pdfFile = req.files.product_manual; + const result = await cloudinary.v2.uploader.upload(pdfFile.tempFilePath, { + folder: "chemiNova/ProductManuals", + resource_type: "raw", // For PDF or other non-image files + }); + + productManualDetails = { + public_id: result.public_id, + url: result.secure_url, + }; + } + + // Create the product manual + const productManual = await ProductManual.create({ + title, + product_manual: productManualDetails, + }); + + res.status(201).json({ + success: true, + productManual, + message: "Product manual created successfully", + }); + } catch (error) { + console.error("Error creating product manual:", error); + res.status(500).json({ + success: false, + message: error.message || "Internal server error", + }); + } +}; + +// Get all product manuals +export const getAllProductManuals = async (req, res) => { + try { + const productManuals = await ProductManual.find(); + res.status(200).json({ + success: true, + productManuals, + }); + } catch (error) { + console.error("Error fetching product manuals:", error); + res.status(500).json({ + success: false, + message: error.message || "Internal server error", + }); + } +}; + +// Get a single product manual by ID +export const getSingleProductManual = async (req, res) => { + const { id } = req.params; + + try { + const productManual = await ProductManual.findById(id); + + if (!productManual) { + return res.status(404).json({ + success: false, + message: "Product manual not found", + }); + } + + res.status(200).json({ + success: true, + productManual, + }); + } catch (error) { + console.error("Error fetching product manual:", error); + res.status(500).json({ + success: false, + message: error.message || "Internal server error", + }); + } +}; + +// Update a product manual +export const updateProductManual = async (req, res) => { + const { id } = req.params; + const { title } = req.body; + + try { + const productManual = await ProductManual.findById(id); + + if (!productManual) { + return res.status(404).json({ + success: false, + message: "Product manual not found", + }); + } + + // Check if a new file is provided + if (req.files && req.files.product_manual) { + // Delete the old file from Cloudinary + if (productManual.product_manual.public_id) { + await cloudinary.v2.uploader.destroy(productManual.product_manual.public_id, { + resource_type: "raw", + }); + } + + // Upload the new file to Cloudinary + const pdfFile = req.files.product_manual; + const result = await cloudinary.v2.uploader.upload(pdfFile.tempFilePath, { + folder: "chemiNova/ProductManuals", + resource_type: "raw", + }); + + // Update the product manual details + productManual.product_manual = { + public_id: result.public_id, + url: result.secure_url, + }; + } + + // Update the title + productManual.title = title || productManual.title; + + await productManual.save(); + + res.status(200).json({ + success: true, + productManual, + message: "Product manual updated successfully", + }); + } catch (error) { + console.error("Error updating product manual:", error); + res.status(500).json({ + success: false, + message: error.message || "Internal server error", + }); + } +}; + +// Delete a product manual +export const deleteProductManual = async (req, res) => { + const { id } = req.params; + + try { + const productManual = await ProductManual.findById(id); + + if (!productManual) { + return res.status(404).json({ + success: false, + message: "Product manual not found", + }); + } + + // Delete the file from Cloudinary + if (productManual.product_manual.public_id) { + await cloudinary.v2.uploader.destroy(productManual.product_manual.public_id, { + resource_type: "raw", + }); + } + + // Delete the product manual from the database + await ProductManual.findByIdAndDelete(id); + + res.status(200).json({ + success: true, + message: "Product manual deleted successfully", + }); + } catch (error) { + console.error("Error deleting product manual:", error); + res.status(500).json({ + success: false, + message: error.message || "Internal server error", + }); + } +}; \ No newline at end of file diff --git a/resources/ProductMannual/ProductManualModel.js b/resources/ProductMannual/ProductManualModel.js new file mode 100644 index 0000000..a21de31 --- /dev/null +++ b/resources/ProductMannual/ProductManualModel.js @@ -0,0 +1,25 @@ +import mongoose from "mongoose"; + +const ProductManualSchema = new mongoose.Schema( + { + title: { + type: String, + required: true, + }, + product_manual: { + public_id: { + type: String, + required: true, + }, + url: { + type: String, + required: true, + }, + }, + }, + { timestamps: true } +); + +const ProductManual = mongoose.model("ProductManual", ProductManualSchema); + +export default ProductManual; diff --git a/resources/ProductMannual/ProductManualRoute.js b/resources/ProductMannual/ProductManualRoute.js new file mode 100644 index 0000000..d48d6c3 --- /dev/null +++ b/resources/ProductMannual/ProductManualRoute.js @@ -0,0 +1,90 @@ +import express from "express"; +import { + createProductManual, + getAllProductManuals, + getSingleProductManual, + updateProductManual, + deleteProductManual, +} from "./ProductManualController.js"; +import { + isAuthenticatedUser, + authorizeRoles, +} from "../../middlewares/auth.js"; +import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; +import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; + +const router = express.Router(); + +// Route for creating a product manual (Only Admin can create) +router + .route("/create") + .post(isAuthenticatedUser, authorizeRoles("admin"), createProductManual); + +// Route for getting all product manuals (accessible to Sales Coordinator, Territory Manager, and Admin) +router.route("/").get( + (req, res, next) => { + // Allow access if the user is a sales coordinator, territory manager, or admin + isAuthenticatedSalesCoOrdinator(req, res, (err) => { + if (err) { + isAuthenticatedTerritoryManager(req, res, (err) => { + if (err) { + isAuthenticatedUser(req, res, (err) => { + if (err || !["admin"].includes(req.user.role)) { + return res.status(403).json({ + success: false, + message: "Access denied. Unauthorized role.", + }); + } + next(); + }); + } else { + next(); + } + }); + } else { + next(); + } + }); + }, + getAllProductManuals +); + +// Route for getting a single product manual by ID (accessible to Sales Coordinator, Territory Manager, and Admin) +router.route("/:id").get( + (req, res, next) => { + // Allow access if the user is a sales coordinator, territory manager, or admin + isAuthenticatedSalesCoOrdinator(req, res, (err) => { + if (err) { + isAuthenticatedTerritoryManager(req, res, (err) => { + if (err) { + isAuthenticatedUser(req, res, (err) => { + if (err || !["admin"].includes(req.user.role)) { + return res.status(403).json({ + success: false, + message: "Access denied. Unauthorized role.", + }); + } + next(); + }); + } else { + next(); + } + }); + } else { + next(); + } + }); + }, + getSingleProductManual +); +// Route to update a product manual by ID +router + .route("/update/:id") + .put(isAuthenticatedUser, authorizeRoles("admin"), updateProductManual); + +// Route to delete a product manual by ID +router + .route("/delete/:id") + .delete(isAuthenticatedUser, authorizeRoles("admin"), deleteProductManual); +export default router; +// /api/productmanual \ No newline at end of file diff --git a/resources/Task/TaskController.js b/resources/Task/TaskController.js index bc382f0..e6ca2a4 100644 --- a/resources/Task/TaskController.js +++ b/resources/Task/TaskController.js @@ -12,6 +12,7 @@ export const assignTask = async (req, res) => { taskAssignedTo, addedFor, addedForId, + tradename, } = req.body; const currentYear = new Date().getFullYear().toString().slice(-2); @@ -29,6 +30,7 @@ export const assignTask = async (req, res) => { taskAssignedBy: req.user._id, addedFor, addedForId, + tradename, }); res.status(201).json({ @@ -73,8 +75,33 @@ export const getTasksByStatus = async (req, res) => { }); } }; +export const getTasksbytask = async (req, res) => { + try { + const { task } = req.params; + // Validate the provided status + if (!["Visit RD/PD", "Update Sales Data", "Update Inventory Data", "Collect KYC"].includes(task)) { + return res.status(400).json({ + success: false, + message: "Invalid task type provided.", + }); + } + const tasks = await Task.find({ + taskAssignedTo: req.user._id, + task: task, + }).sort({ createdAt: -1 }); + res.status(200).json({ + success: true, + tasks, + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message, + }); + } +}; export const updateTaskStatus = async (req, res) => { try { const { taskId } = req.params; diff --git a/resources/Task/TaskModel.js b/resources/Task/TaskModel.js index 988d8b5..0cf0be3 100644 --- a/resources/Task/TaskModel.js +++ b/resources/Task/TaskModel.js @@ -12,12 +12,12 @@ const TaskSchema = new mongoose.Schema( task: { type: String, required: true, - enum: ["Visit Retailers", "Update Sales Data", "Update Inventory Data", "Collect KYC"], + enum: ["Visit RD/PD", "Update Sales Data", "Update Inventory Data", "Collect KYC"], }, note: { type: String, required: function () { - return this.task === "Collect KYC"; + return this.task === "Collect KYC" || this.task === "Visit RD/PD"; }, }, taskStatus: { @@ -60,6 +60,12 @@ const TaskSchema = new mongoose.Schema( return this.task === "Update Inventory Data"; }, }, + tradename: { + type: String, + required: function () { + return this.task === "Update Inventory Data"; + }, + }, }, { timestamps: true } ); diff --git a/resources/Task/TaskRoute.js b/resources/Task/TaskRoute.js index c0eb6ab..a2b639e 100644 --- a/resources/Task/TaskRoute.js +++ b/resources/Task/TaskRoute.js @@ -3,6 +3,7 @@ import { assignTask, getTasksByStatus, updateTaskStatus, + getTasksbytask, } from "./TaskController.js"; import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js"; import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js"; @@ -22,7 +23,11 @@ router.get( isAuthenticatedSalesCoOrdinator, getTasksByStatus ); - +router.get( + "/task/type/:task", + isAuthenticatedSalesCoOrdinator, + getTasksbytask +); // Route to update task status router.put( "/update-task-status/:taskId", diff --git a/resources/user/userController.js b/resources/user/userController.js index 620b722..2e2247d 100644 --- a/resources/user/userController.js +++ b/resources/user/userController.js @@ -563,7 +563,19 @@ export const uploadPrincipaldistributors = async (req, res) => { uniqueId: item.uniqueId, }); await distributor.save(); - + await sendEmail({ + to: distributor.email, + from: process.env.SEND_EMAIL_FROM, + subject: `Cheminova Account Created`, + html: ` + Your Principal Distributor Account is created successfully. +
Name: ${distributor.name}
+
Mobile Number: ${distributor.phone}
+
Password: ${password}

+ Click here to login

+ If you have not requested this email, please ignore it. + `, + }); // Now create the address for the new user const addressData = { street: item.street,