From 382b2820c991fc77d287446d2b9e81d7843502d5 Mon Sep 17 00:00:00 2001 From: Ikki Date: Sun, 10 Nov 2024 16:43:16 +0530 Subject: [PATCH] delivery_schema --- .../deliveryPersonController.js | 269 ++++++++++++++++++ backend/middleware/sub-ware/validate.js | 15 + .../model/shop/sub-model/DeliveryPerson.js | 44 +++ backend/services/sub-service/hashPassword.js | 9 + 4 files changed, 337 insertions(+) create mode 100644 backend/controllers/shop/sub-controllers/deliveryPersonController.js create mode 100644 backend/middleware/sub-ware/validate.js create mode 100644 backend/model/shop/sub-model/DeliveryPerson.js create mode 100644 backend/services/sub-service/hashPassword.js diff --git a/backend/controllers/shop/sub-controllers/deliveryPersonController.js b/backend/controllers/shop/sub-controllers/deliveryPersonController.js new file mode 100644 index 00000000..ea24cc4b --- /dev/null +++ b/backend/controllers/shop/sub-controllers/deliveryPersonController.js @@ -0,0 +1,269 @@ +const DeliveryPerson = require("../../../model/shop/sub-model/DeliveryPerson"); +const { hashPassword } = require("../../../services/sub-service/hashPassword"); +const { + validateEmail, + validatePhoneNumber, +} = require("../../../services/sub-service/couponValidator"); + +exports.successResponse = (res, statusCode, message, data = {}) => { + res.status(statusCode).json({ + status: "success", + message, + data, + }); +}; + +exports.errorResponse = (res, statusCode, message, error = {}) => { + res.status(statusCode).json({ + status: "error", + message, + error, + }); +}; + +// Create a new Delivery Person +exports.createDeliveryPerson = async (req, res) => { + try { + const { + name, + email, + phone_number, + status, + assigned_routes, + vehicle_details, + profile_picture, + password, + } = req.body; + + // Validate required fields + if (!name || !email || !phone_number || !status) { + return errorResponse(res, 400, "All required fields must be provided."); + } + + // Validate email and phone number formats + if (!validateEmail(email)) + return errorResponse(res, 400, "Invalid email format."); + if (!validatePhoneNumber(phone_number)) + return errorResponse(res, 400, "Invalid phone number format."); + + // Check if email already exists + const existingEmail = await DeliveryPerson.findOne({ email }); + if (existingEmail) return errorResponse(res, 400, "Email already exists."); + + // Hash password if provided + const hashedPassword = password ? await hashPassword(password) : undefined; + + const newDeliveryPerson = new DeliveryPerson({ + name, + email, + phone_number, + status, + assigned_routes, + vehicle_details, + profile_picture, + password: hashedPassword, + }); + + await newDeliveryPerson.save(); + successResponse( + res, + 201, + "Delivery person created successfully.", + newDeliveryPerson + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Get all Delivery Persons with pagination +exports.getAllDeliveryPersons = async (req, res) => { + try { + const { page = 1, limit = 10 } = req.query; + const deliveryPersons = await DeliveryPerson.find() + .select("name status vehicle_details.vehicle_type") + .limit(parseInt(limit)) + .skip((parseInt(page) - 1) * parseInt(limit)); + const count = await DeliveryPerson.countDocuments(); + + successResponse(res, 200, "Delivery persons retrieved successfully.", { + deliveryPersons, + totalPages: Math.ceil(count / limit), + currentPage: parseInt(page), + }); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Get a Delivery Person by ID +exports.getDeliveryPersonById = async (req, res) => { + try { + const deliveryPerson = await DeliveryPerson.findById( + req.params.id + ).populate("assigned_routes"); + if (!deliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + successResponse( + res, + 200, + "Delivery person retrieved successfully.", + deliveryPerson + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Update a Delivery Person +exports.updateDeliveryPerson = async (req, res) => { + try { + const updates = req.body; + + // Validate and hash password if provided + if (updates.password) + updates.password = await hashPassword(updates.password); + + // Validate email and phone number if updated + if (updates.email && !validateEmail(updates.email)) + return errorResponse(res, 400, "Invalid email format."); + if (updates.phone_number && !validatePhoneNumber(updates.phone_number)) + return errorResponse(res, 400, "Invalid phone number format."); + + // Check if email already exists (excluding current delivery person) + if (updates.email) { + const existingEmail = await DeliveryPerson.findOne({ + email: updates.email, + _id: { $ne: req.params.id }, + }); + if (existingEmail) + return errorResponse(res, 400, "Email already exists."); + } + + const updatedDeliveryPerson = await DeliveryPerson.findByIdAndUpdate( + req.params.id, + updates, + { new: true } + ); + if (!updatedDeliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + successResponse( + res, + 200, + "Delivery person updated successfully.", + updatedDeliveryPerson + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Soft delete (deactivate) a Delivery Person +exports.deleteDeliveryPerson = async (req, res) => { + try { + const deliveryPerson = await DeliveryPerson.findById(req.params.id); + if (!deliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + + deliveryPerson.status = "inactive"; + await deliveryPerson.save(); + successResponse(res, 200, "Delivery person deactivated successfully."); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Activate or Deactivate Delivery Person +exports.toggleStatus = async (req, res) => { + try { + const { status } = req.body; + if (!["active", "inactive"].includes(status)) + return errorResponse(res, 400, "Invalid status."); + + const deliveryPerson = await DeliveryPerson.findById(req.params.id); + if (!deliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + + deliveryPerson.status = status; + await deliveryPerson.save(); + successResponse(res, 200, "Delivery person status updated successfully.", { + status: deliveryPerson.status, + }); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Helper functions for response handling +const validateVehicleDetails = (vehicleDetails) => { + const { vehicle_type, vehicle_number } = vehicleDetails; + if (vehicle_type && typeof vehicle_type !== "string") return false; + if (vehicle_number && typeof vehicle_number !== "string") return false; + return true; +}; + +// Search Delivery Person by name +exports.searchDeliveryPersonByName = async (req, res) => { + try { + const { name } = req.query; + const deliveryPersons = await DeliveryPerson.find({ + name: { $regex: name, $options: "i" }, + }); + successResponse( + res, + 200, + "Search results retrieved successfully.", + deliveryPersons + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Get all assigned routes for a Delivery Person +exports.getAssignedRoutes = async (req, res) => { + try { + const deliveryPerson = await DeliveryPerson.findById( + req.params.id + ).populate("assigned_routes"); + if (!deliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + successResponse( + res, + 200, + "Assigned routes retrieved successfully.", + deliveryPerson.assigned_routes + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; + +// Change Delivery Person's vehicle details +exports.updateVehicleDetails = async (req, res) => { + try { + const { vehicle_details } = req.body; + + // Validate vehicle details format + if (vehicle_details && !validateVehicleDetails(vehicle_details)) { + return errorResponse(res, 400, "Invalid vehicle details format."); + } + + const updatedDeliveryPerson = await DeliveryPerson.findByIdAndUpdate( + req.params.id, + { vehicle_details }, + { new: true } + ); + + if (!updatedDeliveryPerson) + return errorResponse(res, 404, "Delivery person not found."); + successResponse( + res, + 200, + "Vehicle details updated successfully.", + updatedDeliveryPerson.vehicle_details + ); + } catch (error) { + errorResponse(res, 500, error.message); + } +}; diff --git a/backend/middleware/sub-ware/validate.js b/backend/middleware/sub-ware/validate.js new file mode 100644 index 00000000..792c4a16 --- /dev/null +++ b/backend/middleware/sub-ware/validate.js @@ -0,0 +1,15 @@ + +const { check, validationResult } = require('express-validator'); + +exports.validateDeliveryPerson = [ + check('email').isEmail().withMessage('Email is invalid'), + check('phone_number').isMobilePhone().withMessage('Phone number is invalid'), + check('status').isIn(['active', 'inactive']).withMessage('Status must be active or inactive'), + (req, res, next) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + next(); + } +]; diff --git a/backend/model/shop/sub-model/DeliveryPerson.js b/backend/model/shop/sub-model/DeliveryPerson.js new file mode 100644 index 00000000..03d9afe3 --- /dev/null +++ b/backend/model/shop/sub-model/DeliveryPerson.js @@ -0,0 +1,44 @@ +// models/DeliveryPerson.js +const mongoose = require("mongoose"); + +const deliveryPersonSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + }, + email: { + type: String, + required: true, + unique: true, + }, + phone_number: { + type: String, + required: true, + }, + status: { + type: String, + enum: ["active", "inactive"], + required: true, + }, + assigned_routes: [{ type: mongoose.Schema.Types.ObjectId, ref: "Route" }], + vehicle_details: { + vehicle_type: { type: String }, + vehicle_number: { type: String }, + }, + created_at: { + type: Date, + default: Date.now, + }, + updated_at: { + type: Date, + default: Date.now, + }, + password: { + type: String +}, + profile_picture: { + type: String + }, +}); + +module.exports = mongoose.model("DeliveryPerson", deliveryPersonSchema); diff --git a/backend/services/sub-service/hashPassword.js b/backend/services/sub-service/hashPassword.js new file mode 100644 index 00000000..0c0a30a2 --- /dev/null +++ b/backend/services/sub-service/hashPassword.js @@ -0,0 +1,9 @@ + +const bcrypt = require('bcrypt'); + +const hashPassword = async (password) => { + const salt = await bcrypt.genSalt(10); + return bcrypt.hash(password, salt); +}; + +module.exports = { hashPassword };