Hii Guys!

Let's build the additional features that completes the setup as per our task requirements in continution to 👉Backend Setup

Plan

Step by step implementation of additional steps.

1. CSV Import/Export for Stock Details

  • Allowing admin to upload CSV File to add/update the products.
  • Providing an endpoint to download the current stock data as csv

inorder to perform these steps, create a model and perform actions according to the get and post routes for csv file to store data into the database rather than storageMemory.

  • CSVFile.js
const mongoose = require("mongoose");

const csvFileSchema = new mongoose.Schema({
    filename: String,
    mimetype: String,
    data: Buffer, // Store the CSV file as binary
    uploadedAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model("CSVFile", csvFileSchema);
  • create a middleware for csv file in authMiddleware.js
const multer = require("multer");

const storage = multer.memoryStorage(); // Store file in memory as Buffer
const upload = multer({ storage });

module.exports = {upload};
  • Define route in the server.js inorder to perform the creation of routes and controller actions.

    • csvRoutes.js
const express = require("express");
const { importCSV, exportCSV } = require("../controllers/csvController");
const {upload} = require("../middleware/authMiddleware");

const router = express.Router();

router.post("/import-csv", upload.single("file"), importCSV);
router.get("/export-csv", exportCSV);

module.exports = router;
  • csvController.js
  1. Logic for importing the csv file and storing results in Products file.
const importCSV = async (req, res) => {
    try {
        if (!req.file) {
            return res.status(400).json({ error: "No file uploaded!" });
        }

        // Convert buffer data to stream
        const csvStream = Readable.from(req.file.buffer.toString());

        let products = [];
        csvStream
            .pipe(csv.parse({ headers: true }))
            .on("data", (row) => {
                products.push({
                    name: row["Product Name"], // Mapping CSV column to schema field
                    category: row["Category"],
                    price: parseFloat(row["Price"]), // Ensure numeric value
                    stockQuantity: parseInt(row["Stock Quantity"]), // Ensure integer
                    itemsSold: parseInt(row["Items Sold"]) // Ensure integer
                });
            })
            .on("end", async () => {
                try {
                    await Product.insertMany(products);
                    res.status(200).json({ message: "CSV imported successfully and stored in DB!" });
                } catch (err) {
                    console.error("Error inserting data:", err);
                    res.status(500).json({ error: "Error inserting data" });
                }
            });

    } catch (error) {
        console.error("CSV Import Error:", error);
        res.status(500).json({ error: "Error importing CSV" });
    }
};
  1. Logic for the exporting the products data in the form of csv file.
const exportCSV = async (req, res) => {
    try {
        // Find the most recent CSV file from the database
        const latestFile = await CSVFile.findOne().sort({ uploadedAt: -1 });

        if (!latestFile) {
            return res.status(404).json({ error: "No CSV file found" });
        }

        res.setHeader("Content-Type", latestFile.mimetype);
        res.setHeader("Content-Disposition", `attachment; filename=${latestFile.filename}`);
        res.send(latestFile.data);
    } catch (error) {
        res.status(500).json({ error: "Error exporting CSV" });
    }
};

and export the functions inorder to get referenced to the routes, to perform action with respect to the route.

2. Filters and Sorting on Stock Overview

  • Implementing query parameters for filtering and sorting stock data.
  • Define the routes for the analytics in server.js
app.use("/api/analytics", analyticsRoutes);
  • analyticsRoutes.js
const express = require('express');
const { getStockData, getChartData } = require('../controllers/analyticsController');

const router = express.Router();
router.get('/stock', getStockData); //Fetching stock with filters.

router.get('/chart-data', getChartData);//fetching the data for presenting in chart.


module.exports = router;
  • Then complete the controller functions to complete the actions to their respective routes.

by requiring the Products model, to the analyticsController.js

  • functions, 1.Filters Products by Category If a category query parameter is provided (e.g., /stock?category=Fruits), it filters products based on that category.

2.Sorts Products Based on Query Parameters
If sortBy is provided (e.g., /stock?sortBy=price), it sorts the results:
Ascending (asc or default) → order=1
Descending (desc) → order=-1

Example:

/stock?sortBy=price&order=desc → Sorts by price in descending order

3.Finds and Returns Sorted & Filtered Data
Applies filtering (filter) if category is provided.

Applies sorting (sortOptions) if sortBy and order are given.

const getStockData = async (req, res) => {
    try {
        let { category, sortBy, order } = req.query;
        let filter = {};
        let sortOptions = {};

        if (category) filter.category = category;
        if (sortBy) sortOptions[sortBy] = order === "desc" ? -1 : 1;

        const products = await Product.find(filter).sort(sortOptions);
        res.status(200).json(products);
    } catch (error) {
        res.status(500).json({ message: "Error fetching stock data", error });
    }
};

3. Display Charts for Stock Trends and Revenue

analyticsController.js

const getChartData = async (req, res) => {
    try {
        const products = await Product.find();

        const categories = {};
        products.forEach(product => {
            if (!categories[product.category]) {
                categories[product.category] = { totalRevenue: 0, totalSold: 0 };
            }
            categories[product.category].totalRevenue += product.totalRevenue;
            categories[product.category].totalSold += product.itemsSold;
        });

        const chartData = Object.keys(categories).map(category => ({
            category,
            totalRevenue: categories[category].totalRevenue,
            totalSold: categories[category].totalSold
        }));

        res.status(200).json(chartData);
    } catch (error) {
        res.status(500).json({ message: "Error fetching chart data", error });
    }
};

4. Test your backend api

I have tested everyting in here just visit the link for testing the api.

5. Deployment Of Backend API

  • Create a repository Stock-Management-Api.

  • Push the code to this repo.

  • verify my repo to get the code.GithubLink

  • create vercel.json file in root directory inorder to handle the deployment in vercel.

{
    "version": 2,
    "builds": [
      {
        "src": "server.js",
        "use": "@vercel/node"
      }
    ],
    "routes": [
      {
        "src": "/(.*)",
        "dest": "server.js"
      }
    ]
  }
  • go to vercel.com create an account and add a new project for deployment.

Image description

  • Select your repo and import it.

Image description

  • Provide the environment variables and path to root directory.

Image description

  • Then click on deploy.

Image description

Congratulations! U just deployed your backend API.

Happy Developing.

Let's continue frontend part in upcoming blogs.For any queries reach out in comment section.

Thank You!

                       Let's grow together!

Image description