Skip to content

An inventory management app for a hypothetical shop hardWareHouse that uses Redis as its primary database.

License

Notifications You must be signed in to change notification settings

pranavarora1895/hardWareHouseInventory

Repository files navigation

hardWareHouse Inventory Management Application

Runner-up of Redis x DevTo Competition. View here -> devto-runner-up

An inventory management application for a shop to keep the track of its products data. It uses Redis as its primary database, Flask as the backend that connects with Redis, and React as the frontend that renders the data on the browser.

architecture
appPage
hardWareHouse Inventory Dashboard
newProduct
Way to Add a new Product
editProduct
Way to Update any Product
searchProduct
Search a Product and the table will render accordingly

Overview video

Here's a short video that explains the project and how it uses Redis:

hardwarehouseYoutubeThumbnail

Technical Stack

  • Database: Redis
  • Backend: Flask
  • Frontend: React

How it works

How the data is stored:

  • From redis_om module, following are used to create the Product schema:

    • JsonModel
    • Field
  • The product data is stored in various keys and various data types.

    • product_name: str
    • product_desc: str
    • price: PositiveInt
    • units: PositiveInt
    • lower_limit_stock: PositiveInt
    • timestamp: datetime
from redis_om import Field, JsonModel
from pydantic import PositiveInt
from datetime import datetime
# Added Product Schema


class Product(JsonModel):

    product_name: str = Field(index=True, full_text_search=True)
    product_desc: str = Field(index=True)
    price: PositiveInt = Field(index=True)
    units: PositiveInt = Field(index=True)
    lower_limit_stock: PositiveInt = Field(index=True)
    timestamp: datetime = Field(index=True, default=datetime.now())
newProduct
Way to Add a new Product
  • When user clicks on the Add Product button on the dashboard, the addProduct method triggers the following POST request from the frontend.
  const addProduct = async (product_name, product_desc, price, units, lower_limit_stock) => {
    // POST API Call
    try {
      const url = `${host}/product/new`;
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },

        body: JSON.stringify({
          product_name,
          product_desc,
          price: parseInt(price),
          units: parseInt(units),
          lower_limit_stock: parseInt(lower_limit_stock),
        }),
      });
      const json = await response.json();
    } catch (error) {
      console.error(error);
    }
  };
  • This invokes the create_product() method in the backend that handles the POST request. It performs the relevant validations and then saves the data in the database.
@app.route("/product/new", methods=["POST"])
def create_product():
    try:
        print(request.json)
        new_product = Product(**request.json)
        new_product.save()
        return json.dumps(new_product.pk)

    except ValidationError as e:
        print(e)
        return "Bad request.", 400
  • The product update also follows the similar pattern.

  • Sample data stored: Key Name: :product.Product:01G9W6KP7S4K3DS3BRD5AEREDX

{
pk: "01G9VZ5C9PPXF3WYYB7JYN8WAR",
product_name: "Mechanical Keyboard",
product_desc: "Built for extensive typing",
price: 8250,
units: 23,
lower_limit_stock: 5,
timestamp: "2022-08-07T16:25:04.834860",
}

How the data is accessed:

  • The GET request is initiated from the frontend.
   const getAllProducts = async () => {
    try {
      const url = `${host}/product/fetchall/`;
      const response = await fetch(url, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
      });
      const json = await response.json();
    } catch (error) {
      console.error(error);
    }
  };
  • This invokes the fetch_all_products() method in the backend that handles the GET request. It sorts the data by timestamp in descending order and returns an array of fetched products.
@app.route("/product/fetchall/", methods=["GET"])
def fetch_all_products():
    products = Product.find().sort_by("-timestamp").all()
    return build_results(products)

How to run it locally?

Prerequisites

  • Python - v3.8.5
  • Docker - v20.10.17
  • Nodejs - v8.11.0

Local installation

  1. Clone the repository from github
git clone https://github.com/pranavarora1895/hardWareHouseInventory.git
  1. Server Side: Make sure your docker is up and running. Go to hardWareHouseInventory\hardWareHouseInventory\ folder and then:
# Go to server side
cd .\hardWareHouseInventory\hardWareHouseInventory\

# Get redis image
docker compose up -d

# Create virtual env
python -m venv venv

# Activate env for powershell
.\venv\Scripts\Activate.ps1

# Install dependencies
pip install -r requirements.txt

# Run server
flask run
  1. To load some sample data, run productsloader.py script in the hardWareHouseInventory\hardWareHouseInventory\ folder:
# Open a new PowerShell window
cd .\hardWareHouseInventory\hardWareHouseInventory\

.\venv\Scripts\Activate.ps1

python .\productsloader.py

# After loading the products, you can close that powershell window
  1. Client Side: Go to hardWareHouseInventory\hardwarehouse-dashboard\ folder and then:
# Open another powershell window
cd .\hardWareHouseInventory\hardwarehouse-dashboard\

# Install dependencies
npm install

# Start the client server
npm run start

Thank You!!

Let's get connected:

devto facebook linkedin instagram

Time taken to build this app: wakatime

About

An inventory management app for a hypothetical shop hardWareHouse that uses Redis as its primary database.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project