diff --git a/Backend/Controllers/crop.controller.js b/Backend/Controllers/crop.controller.js index e69de29..60c3930 100644 --- a/Backend/Controllers/crop.controller.js +++ b/Backend/Controllers/crop.controller.js @@ -0,0 +1,128 @@ +import Crop from "../models/cropModel.js"; +import Farm from "../models/farmModel.js"; + +// Create a new crop +export const createCrop = async (req, res) => { + try { + const { name, farm, image, harvestDate, growthStage, healthStatus } = + req.body; + + // Check if the farm exists + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + const crop = new Crop({ + name, + farm, + image, + harvestDate, + growthStage, + healthStatus, + }); + + await crop.save(); + + // Add crop to farm + existingFarm.crops.push(crop._id); + await existingFarm.save(); + + res.status(201).json(crop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all crops for a specific farm +export const getCropsByFarm = async (req, res) => { + try { + const crops = await Crop.find({ farm: req.params.farmId }); + + res.status(200).json(crops); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single crop by ID +export const getCropById = async (req, res) => { + try { + const crop = await Crop.findById(req.params.cropId).populate("farm"); + + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + res.status(200).json(crop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop details +export const updateCrop = async (req, res) => { + try { + const updatedCrop = await Crop.findByIdAndUpdate( + req.params.cropId, + req.body, + { new: true } + ); + + if (!updatedCrop) + return res.status(404).json({ message: "Crop not found" }); + + res.status(200).json(updatedCrop); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a crop +export const deleteCrop = async (req, res) => { + try { + const crop = await Crop.findById(req.params.cropId); + + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + await crop.deleteOne(); + + // Remove crop from the farm + await Farm.findByIdAndUpdate(crop.farm, { $pull: { crops: crop._id } }); + + res.status(200).json({ message: "Crop deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop growth stage +export const updateGrowthStage = async (req, res) => { + try { + const { growthStage } = req.body; + + const crop = await Crop.findById(req.params.cropId); + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + crop.growthStage = growthStage; + await crop.save(); + + res.status(200).json({ message: "Growth stage updated", crop }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update crop health status +export const updateHealthStatus = async (req, res) => { + try { + const { healthStatus } = req.body; + + const crop = await Crop.findById(req.params.cropId); + if (!crop) return res.status(404).json({ message: "Crop not found" }); + + crop.healthStatus = healthStatus; + await crop.save(); + + res.status(200).json({ message: "Health status updated", crop }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/farm.controller.js b/Backend/Controllers/farm.controller.js index e69de29..1e44f11 100644 --- a/Backend/Controllers/farm.controller.js +++ b/Backend/Controllers/farm.controller.js @@ -0,0 +1,130 @@ +const Farm = require("../Models/farm.model.js"); +const Crop = require("../Models/crop.model.js"); +const Finance = require("../Models/finance.model.js"); + +// Create a farm +const createFarm = async (req, res) => { + try { + const { name, location, waterContent, soilType } = req.body; + + const farm = new Farm({ + name, + location, + waterContent, + soilType, + owner: req.user._id, + }); + + await farm.save(); + res.status(201).json(farm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all farms for a user +const getUserFarms = async (req, res) => { + try { + const farms = await Farm.find({ owner: req.user._id }) + .populate("crops") + .populate("finances"); + + res.status(200).json(farms); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single farm by ID +const getFarmById = async (req, res) => { + try { + const farm = await Farm.findById(req.params.farmId) + .populate("crops") + .populate("finances"); + + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + res.status(200).json(farm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update farm details +const updateFarm = async (req, res) => { + try { + const updatedFarm = await Farm.findByIdAndUpdate( + req.params.farmId, + req.body, + { new: true } + ); + + if (!updatedFarm) + return res.status(404).json({ message: "Farm not found" }); + + res.status(200).json(updatedFarm); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a farm +const deleteFarm = async (req, res) => { + try { + const farm = await Farm.findById(req.params.farmId); + + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + await Crop.deleteMany({ farm: farm._id }); + await Finance.findByIdAndDelete(farm.finances); + await farm.deleteOne(); + + res.status(200).json({ message: "Farm deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add fertilizer to a farm +const addFertilizer = async (req, res) => { + try { + const { name, quantity } = req.body; + + const farm = await Farm.findById(req.params.farmId); + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + farm.fertilizer.push({ name, quantity }); + await farm.save(); + + res.status(200).json({ message: "Fertilizer added", farm }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add pesticide to a farm +const addPesticide = async (req, res) => { + try { + const { name, quantity } = req.body; + + const farm = await Farm.findById(req.params.farmId); + if (!farm) return res.status(404).json({ message: "Farm not found" }); + + farm.pestisides.push({ name, quantity }); + await farm.save(); + + res.status(200).json({ message: "Pesticide added", farm }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +module.exports = { + createFarm, + getUserFarms, + getFarmById, + updateFarm, + deleteFarm, + addFertilizer, + addPesticide, +}; diff --git a/Backend/Controllers/finance.controller.js b/Backend/Controllers/finance.controller.js index e69de29..a60683c 100644 --- a/Backend/Controllers/finance.controller.js +++ b/Backend/Controllers/finance.controller.js @@ -0,0 +1,126 @@ +import Finance from "../models/financeModel.js"; +import Farm from "../models/farmModel.js"; + +// Create finance record for a farm +export const createFinance = async (req, res) => { + try { + const { farm } = req.body; + + // Check if the farm exists + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + const finance = new Finance({ + farm, + transactions: [], + totalExpenses: 0, + totalRevenue: 0, + }); + + await finance.save(); + + // Link finance to farm + existingFarm.finances = finance._id; + await existingFarm.save(); + + res.status(201).json(finance); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get finance details by farm ID +export const getFinanceByFarm = async (req, res) => { + try { + const finance = await Finance.findOne({ farm: req.params.farmId }); + + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json(finance); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Add a transaction (expense/revenue) +export const addTransaction = async (req, res) => { + try { + const { type, amount, description } = req.body; + + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + finance.transactions.push({ type, amount, description }); + + // Update totals + if (type === "Expense") { + finance.totalExpenses += amount; + } else if (type === "Revenue") { + finance.totalRevenue += amount; + } + + await finance.save(); + res.status(200).json({ message: "Transaction added", finance }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a transaction +export const deleteTransaction = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + const transaction = finance.transactions.id(req.params.transactionId); + if (!transaction) + return res.status(404).json({ message: "Transaction not found" }); + + // Adjust totals before removing + if (transaction.type === "Expense") { + finance.totalExpenses -= transaction.amount; + } else if (transaction.type === "Revenue") { + finance.totalRevenue -= transaction.amount; + } + + transaction.remove(); + await finance.save(); + + res.status(200).json({ message: "Transaction deleted", finance }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all transactions for a farm's finance +export const getTransactions = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json(finance.transactions); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get total expenses and revenue +export const getFinancialSummary = async (req, res) => { + try { + const finance = await Finance.findById(req.params.financeId); + if (!finance) + return res.status(404).json({ message: "Finance record not found" }); + + res.status(200).json({ + totalExpenses: finance.totalExpenses, + totalRevenue: finance.totalRevenue, + }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/task.controller.js b/Backend/Controllers/task.controller.js index e69de29..07f12fe 100644 --- a/Backend/Controllers/task.controller.js +++ b/Backend/Controllers/task.controller.js @@ -0,0 +1,111 @@ +import Task from "../models/taskModel.js"; +import Farm from "../models/farmModel.js"; +import Crop from "../models/cropModel.js"; + +// Create a new task +export const createTask = async (req, res) => { + try { + const { farm, crop, taskType, description, assignedDate, status } = + req.body; + + // Validate farm existence + const existingFarm = await Farm.findById(farm); + if (!existingFarm) + return res.status(404).json({ message: "Farm not found" }); + + // Validate crop if provided + if (crop) { + const existingCrop = await Crop.findById(crop); + if (!existingCrop) + return res.status(404).json({ message: "Crop not found" }); + } + + const task = new Task({ + farm, + crop, + taskType, + description, + assignedDate, + status, + }); + + await task.save(); + res.status(201).json(task); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get all tasks for a specific farm +export const getTasksByFarm = async (req, res) => { + try { + const tasks = await Task.find({ farm: req.params.farmId }).populate("crop"); + + res.status(200).json(tasks); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Get a single task by ID +export const getTaskById = async (req, res) => { + try { + const task = await Task.findById(req.params.taskId).populate("farm crop"); + + if (!task) return res.status(404).json({ message: "Task not found" }); + + res.status(200).json(task); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update task details +export const updateTask = async (req, res) => { + try { + const updatedTask = await Task.findByIdAndUpdate( + req.params.taskId, + req.body, + { new: true } + ); + + if (!updatedTask) + return res.status(404).json({ message: "Task not found" }); + + res.status(200).json(updatedTask); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Delete a task +export const deleteTask = async (req, res) => { + try { + const task = await Task.findById(req.params.taskId); + + if (!task) return res.status(404).json({ message: "Task not found" }); + + await task.deleteOne(); + + res.status(200).json({ message: "Task deleted successfully" }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + +// Update task status (Pending → Completed) +export const updateTaskStatus = async (req, res) => { + try { + const { status } = req.body; + + const task = await Task.findById(req.params.taskId); + if (!task) return res.status(404).json({ message: "Task not found" }); + + task.status = status; + await task.save(); + + res.status(200).json({ message: "Task status updated", task }); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/Backend/Controllers/user.controller.js b/Backend/Controllers/user.controller.js index be55245..ff83e6c 100644 --- a/Backend/Controllers/user.controller.js +++ b/Backend/Controllers/user.controller.js @@ -260,6 +260,8 @@ const resetPassword = catchAsyncErrors(async (req, res) => { // get user personal details const getUserDetails = catchAsyncErrors(async (req, res) => { + + const user = await User.findById(req.user._id); if (!user) { diff --git a/Backend/Middlewares/authentication.js b/Backend/Middlewares/authentication.js index 601fbd1..6503546 100644 --- a/Backend/Middlewares/authentication.js +++ b/Backend/Middlewares/authentication.js @@ -1,32 +1,35 @@ const jwt = require("jsonwebtoken"); const User = require("../Models/user.model.js"); +const dotenv = require("dotenv"); +dotenv.config({ + path: "./.env", +}); -function checkAuthenticated() { - return async (req, res, next) => { - const tokenValue = req.cookies[process.env.TOKEN_NAME]; +async function checkAuthenticated(req, res, next) { + const tokenValue = req.cookies[process.env.TOKEN_NAME]; - // console.log("I am called",tokenValue); - if (!tokenValue) { + console.log("I am called", tokenValue); + if (!tokenValue) { + return res.status(404).json({ + success: false, + message: "User is not logged in.", + }); + } + try { + const payload = await jwt.verify( + tokenValue, + process.env.REFRESH_TOKEN_SECRET + ); + + if (!payload) { return next(); } - try { - const payload = await jwt.verify( - tokenValue, - process.env.REFRESH_TOKEN_SECRET - ); - if (!payload) { - return next(); - } - - req.user = await User.findById(payload._id).select("-password"); - - return next(); - } catch (error) { - return next(); - } + req.user = payload; return next(); - }; + } catch (error) { + return next(); + } } function authorizeRoles(...roles) { diff --git a/Backend/Middlewares/multer.js b/Backend/Middlewares/multer.js index 237e292..87bab6f 100644 --- a/Backend/Middlewares/multer.js +++ b/Backend/Middlewares/multer.js @@ -1,7 +1,6 @@ const multer = require("multer"); const storage = multer.diskStorage({ - destination: function (req, file, cb) { cb(null, "./public/images"); }, @@ -10,11 +9,8 @@ const storage = multer.diskStorage({ const uniquePrefix = Date.now(); cb(null, uniquePrefix + "-" + file.originalname); }, - - }); - const upload = multer({ storage: storage }); module.exports = upload; diff --git a/Backend/Models/crop.model.js b/Backend/Models/crop.model.js index b89c83e..a406411 100644 --- a/Backend/Models/crop.model.js +++ b/Backend/Models/crop.model.js @@ -4,6 +4,7 @@ const cropSchema = new mongoose.Schema( { name: { type: String, required: true }, farm: { type: mongoose.Schema.Types.ObjectId, ref: "Farm", required: true }, + image: { type: String }, plantedDate: { type: Date, required: true, default: Date.now() }, harvestDate: { type: Date }, growthStage: { diff --git a/Backend/Routes/crop.routes.js b/Backend/Routes/crop.routes.js new file mode 100644 index 0000000..38fd0f1 --- /dev/null +++ b/Backend/Routes/crop.routes.js @@ -0,0 +1,20 @@ +import express from "express"; +import { + createCrop, + getCrops, + getCropById, + updateCrop, + deleteCrop, +} from "../controllers/cropController.js"; +import { checkAuthenticated } from "../Middlewares/authentication.js"; + +const router = express.Router(); + +// Routes for crop management +router.post("/", checkAuthenticated, createCrop); // Create a new crop +router.get("/", checkAuthenticated, getCrops); // Get all crops +router.get("/:cropId", checkAuthenticated, getCropById); // Get a crop by ID +router.put("/:cropId", checkAuthenticated, updateCrop); // Update crop details +router.delete("/:cropId", checkAuthenticated, deleteCrop); // Delete a crop + +export default router; diff --git a/Backend/Routes/farm.routes.js b/Backend/Routes/farm.routes.js new file mode 100644 index 0000000..caa74c6 --- /dev/null +++ b/Backend/Routes/farm.routes.js @@ -0,0 +1,19 @@ +const express = require("express"); +const { + createFarm, + getUserFarms, + getFarmById, + updateFarm, + deleteFarm, +} = require("../Controllers/farm.controller.js"); +const { checkAuthenticated } = require("../Middlewares/authentication.js"); + +const router = express.Router(); + +router.post("/", checkAuthenticated, createFarm); // Create a new farm +router.get("/", checkAuthenticated, getUserFarms); // Get all farms +router.get("/:farmId", checkAuthenticated, getFarmById); // Get a farm by ID +router.put("/:farmId", checkAuthenticated, updateFarm); // Update a farm +router.delete("/:farmId", checkAuthenticated, deleteFarm); // Delete a farm + +module.exports = router; diff --git a/Backend/Routes/finance.routes.js b/Backend/Routes/finance.routes.js new file mode 100644 index 0000000..4de0e0f --- /dev/null +++ b/Backend/Routes/finance.routes.js @@ -0,0 +1,24 @@ +import express from "express"; +import { + createFinanceRecord, + getFinanceRecords, + getFinanceById, + updateFinance, + deleteFinance, + addTransaction, +} from "../controllers/financeController.js"; +import { checkAuthenticated } from "../Middlewares/authentication.js"; + +const router = express.Router(); + +// Routes for finance management +router.post("/", checkAuthenticated, createFinanceRecord); // Create a new finance record +router.get("/", checkAuthenticated, getFinanceRecords); // Get all finance records +router.get("/:financeId", checkAuthenticated, getFinanceById); // Get a finance record by ID +router.put("/:financeId", checkAuthenticated, updateFinance); // Update finance record +router.delete("/:financeId", checkAuthenticated, deleteFinance); // Delete a finance record + +// Add transactions (Expense/Revenue) to a finance record +router.post("/:financeId/transaction", checkAuthenticated, addTransaction); + +export default router; diff --git a/Backend/Routes/task.routes.js b/Backend/Routes/task.routes.js new file mode 100644 index 0000000..0470aea --- /dev/null +++ b/Backend/Routes/task.routes.js @@ -0,0 +1,24 @@ +import express from "express"; +import { + createTask, + getTasksByFarm, + getTaskById, + updateTask, + deleteTask, + updateTaskStatus, +} from "../controllers/taskController.js"; +const { checkAuthenticated } = require("../Middlewares/authentication.js"); + +const router = express.Router(); + +// Routes for task management +router.post("/", checkAuthenticated, createTask); // Create a new task +router.get("/farm/:farmId", checkAuthenticated, getTasksByFarm); // Get all tasks for a specific farm +router.get("/:taskId", checkAuthenticated, getTaskById); // Get a task by ID +router.put("/:taskId", checkAuthenticated, updateTask); // Update task details +router.delete("/:taskId", checkAuthenticated, deleteTask); // Delete a task + +// Update task status (Pending → Completed) +router.patch("/:taskId/status", protect, updateTaskStatus); + +export default router; diff --git a/Backend/Routes/user.routes.js b/Backend/Routes/user.routes.js index b615ec0..0cd4380 100644 --- a/Backend/Routes/user.routes.js +++ b/Backend/Routes/user.routes.js @@ -33,7 +33,7 @@ router.route("/logout").get(logoutUser); router.route("/update/:id").put(updateUserDetails); -router.route("/me").get(getUserDetails); +router.route("/me").get(checkAuthenticated, getUserDetails); router.route("/getuser").get(intializeUser); @@ -45,6 +45,8 @@ router.route("/user/delete/:id").delete(DeleteUser); router.route("/user/updateRole/:id").put(updateUserRole); -router.route("/user/avatar").put(checkAuthenticated(),upload.single("avatar"), updateAvatar); +router + .route("/user/avatar") + .put(checkAuthenticated, upload.single("avatar"), updateAvatar); module.exports = router; diff --git a/Backend/app.js b/Backend/app.js index 4846a34..145fba4 100644 --- a/Backend/app.js +++ b/Backend/app.js @@ -4,6 +4,8 @@ const cookieParser = require("cookie-parser"); const { Server } = require("socket.io"); const { createServer } = require("http"); const userRoute = require("./Routes/user.routes.js"); +const farmRoute = require("./Routes/farm.routes.js"); + const { checkAuthenticated } = require("./Middlewares/authentication.js"); const dotenv = require("dotenv"); @@ -31,4 +33,6 @@ app.get("/", (req, res) => { app.use("/api/v1", userRoute); +app.use("/api/v1/farm", farmRoute); + module.exports = app;