Building a Warehouse Management CLI with Python, Click, and SQLAlchemy

Managing a warehouse just got a whole lot cooler! This article will explore a Warehouse Management Command-Line Interface (CLI) built with Python, Click, and SQLAlchemy. This handy tool lets you effortlessly perform CRUD (Create, Read, Update, Delete) operations on your warehouse's categories, employees, and products. This walk-through assumes you already have python , click , and SQLAlchemy setup.


Database Connection

At the heart of our warehouse management system lies the database connection. In our model.py script, we've laid the foundation for connecting to the database using SQLAlchemy.

# imports
from sqlalchemy import create_engine, Integer, Column, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

# Connection string and Database setup
conn = 'sqlite:///wharehouse.db'

engine = create_engine(conn)

Base = declarative_base()

# Session
Session = sessionmaker(bind=engine)

session = Session()

Here, the connection string sqlite:///wharehouse.db signifies an SQLite database named wharehouse.db. The engine and Session objects facilitate communication with the database, setting the stage for our warehouse management.


Defining our Models

Next, we work on our models. The warehouse is not just a physical space; it's a digital entity with categories, employees, and products. Let's delve into the models that bring this digital realm to life.

Category Model

The Category model captures the essence of product categories, linking to the Product model.

class Category(Base):
    __tablename__ = "categories"
    id = Column(Integer(), primary_key=True)
    category_name = Column(String(150), nullable=False)

    # Relationship
    products = relationship("Product", backref="category")

    def __repr__(self):
        return f"Category id: {self.id} Category name: {self.category_name}"

Employee Model

The Employee model represents the workforce, linking to products created by employees.

class Employee(Base):
    __tablename__ = "employees"
    id = Column(Integer(), primary_key=True)
    employee_firstname = Column(String(50), nullable=False)
    employee_lastname = Column(String(50), nullable=False)
    employee_email = Column(String(50), nullable=False)

    # Relationship
    products = relationship("Product", backref="employee")

    def __repr__(self):
        return f"Employee id: {self.id}, FirstName: {self.employee_firstname}, LastName: {self.employee_lastname}"

Product Model

The Product model encapsulates the details of products in your warehouse, linking to both categories and employees.

class Product(Base):
    __tablename__ = "products"
    id = Column(Integer(), primary_key=True)
    product_name = Column(String(50), nullable=False)
    product_size = Column(Integer(), nullable=False)
    product_quantity = Column(Integer(), nullable=False)
    product_category = Column(Integer, ForeignKey('categories.id'))
    added_by = Column(Integer(), ForeignKey('employees.id'))

    def __repr__(self):
        return f"Product id: {self.id}, Product name: {self.product_name}, Product size: {self.product_size}, Product quantity: {self.product_quantity}"

Initializing the Database

To bring these models to life, you simply add the following line at the end of the script:

Base.metadata.create_all(engine)

This command instructs SQLAlchemy to create the necessary tables in your database based on the defined models. Once everything Is set correctly, run python model.py. This command initializes your database, creating tables for categories, employees, and products.


Now we have successfully set up the backbone of our Warehouse Management System. The next step involves creating a CLI using Click to interact with this database and manage your warehouse effortlessly.

CRUD Operations with click

Now, it's time to extend the functionality by adding CRUD (Create, Read, Update, Delete) operations specifically for categories. Our CLI, built with Python and Click, will empower you to manage your warehouse categories effortlessly.

Setting the Stage

Before we delve into the details, let's ensure we have the necessary imports and a functioning main function to execute our commands in our main.py:

import click
from terminaltables import AsciiTable
from model import Product, Category, Employee, session

@click.group()
@click.version_option(version="1.0", prog_name="Warehouse Manager CLI")
def main():
    """Simple Warehouse Manager CLI"""
    pass

This snippet establishes a Click command group and defines the main function, acting as the entry point for our CLI.

Adding a Category

Let's start by enabling the addition of new categories to our warehouse. The add_category command prompts users for a category name and seamlessly integrates it into the database.

# ADD CATEGORY
@main.command() 
@click.option('--name','-cn',prompt="Category Name")
def add_category(name):
    """Adds Product Categories to Database"""

    category_data = [
        ['Category Data','Category Value'],
        ['Category Name',name]
    ]
    category_table = AsciiTable(category_data)
    click.echo(category_table.table)
    new_category = Category(category_name = name)
    session.add(new_category)
    session.commit()

    click.secho("Saved Input to Category Table",fg="yellow")

Run the command on your terminal:

python main.py add_category

You'll be prompted to enter the category name, and voila! Your new category is seamlessly integrated into your warehouse database.

Display Categories

Wondering what categories are currently available in your warehouse? The show_categories command provides a neat ASCII table with all the category details.

# DISPLAY CATEGORIES
@main.command() 
def show_categories():
    """Shows all available categories in Category Table"""
    all_categories = session.query(Category).all()
    click.secho("All Available Categories shown below",fg="yellow")

    category_data = [["Category Id", "Category Name"]]
    for category in all_categories:
        category_data.append([category.id, category.category_name])

    category_table = AsciiTable(category_data)

    click.echo(category_table.table)

Run the command on your terminal:

python main.py show_categories

You'll get an overview of all categories in your warehouse, neatly presented in a table.

Updating Category Names

Categories evolve, and sometimes names need a tweak. The update_category command allows you to modify category names effortlessly.

# UPDATE CATEGORIES
@main.command()
@click.option('--originalname','-on',prompt="Original Name")
@click.option('--newname','-nn',prompt="New Name")
def update_category(originalname, newname):
    """Update Category Name"""
    category_update = session.query(Category).filter(Category.category_name == originalname).first()
    category_update.category_name = newname
    session.commit()

    click.secho("Category Name Updated",fg="green")

Run the command on your terminal:

python main.py update_category

Enter the original and new names and your category is updated in the blink of an eye.

Deleting Categories

Spring cleaning in your warehouse? The delete_category command allows you to remove categories with ease.

# DELETE CATEGORY
@main.command()
@click.option('--categoryname','-on',prompt="Category Name")
def delete_category(categoryname):
    """Deletes Category"""
    category = session.query(Category).filter(Category.category_name == categoryname).first()
    session.delete(category)
    session.commit()

    click.secho(f"Category {categoryname} Deleted",fg="red")

if __name__ == "__main__":
    main()

Run the command:

python main.py delete_category

Enter the category name, and poof, it's gone!


In this journey, we've elevated our Warehouse Management System by seamlessly integrating CRUD operations for categories. Leveraging the power of Python, Click, and SQLAlchemy, we've empowered users to effortlessly add, display, update, and delete categories with a few simple commands.

Here's the link to the repo if you feel stuck. Keep an eye out for more insightful articles. Until then, may your warehouse be organized. Happy exploring!