DEV Community

Reshma Shaik
Reshma Shaik

Posted on

Stock Management System - Backend Deployment

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);

Enter fullscreen mode Exit fullscreen mode
  • 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};
Enter fullscreen mode Exit fullscreen mode
  • 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;

Enter fullscreen mode Exit fullscreen mode
  • 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" });
    }
};

Enter fullscreen mode Exit fullscreen mode
  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" });
    }
};

Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode
  • 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;

Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

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 });
    }
};
Enter fullscreen mode Exit fullscreen mode

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 });
    }
};

Enter fullscreen mode Exit fullscreen mode

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"
      }
    ]
  }

Enter fullscreen mode Exit fullscreen mode
  • 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

Top comments (0)