Build a Pharmacy Inventory manager with Django.
Published: 2020-10-31 08:41:29

In this article, I am going to explain how to build an inventory manager for a pharmacy.

The aim of the app was to be able to do the following:

1) The user can create a database table of each item, the item category, unit price and total quantity in stock.
2) User can click on an item, buy it, and generate a receipt.
3) Within the receipt page, the total cost of the item is calculated based on the quantity purchased and the unit price.
4) The balance to be received is also calculated by subtracting the total cost from the amount paid.
5) Based on products sold, a database table of all sales made is created the keeps track of the following:
-The total amount paid summed up for all the items sold.
-The total balance received by all customers also summed up.
-Net balance after subtracting total balance received from total amout paid.
6) The app keeps a log of the quantity remaining in stock for each item as it is being sold.
7) The app is also able to replenish depleting stock in the Products quantity table.

Please note that this tutorial assumes a baseline knowledge of python and Django and that you have django already installed. We will be using Bootstrap 4 and crispy forms for the styling.

Create a new project

```python
django-admin startproject pharmacy_project
```
Change into the pharmacy_project directory and create a new app

```python
cd pharmacy_project
python manage.py startapp product_app
```
Add the newly created app into installed apps under 'settings.py' 

```python
INSTALLED_APPS = [
'product_app',
]
```

In the root directory, create a 'templates' folder and add it within 'settings.py'

```python
TEMPLATES = [
 'DIRS': [os.path.join(BASE_DIR, 'templates')],
]
```

Within the 'product_app' create a 'static' folder and  add a path and a static root within settings.py

```python
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIR = [
    os.path.join(BASE_DIR, 'product_app/static')
]
```
In product_app, create a 'urls.py' file and within the 'pharmacy_project' urls.py file, include the path to the product_app 's  urls.py file 

```python
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include ('product_app.urls'))
]
```

In product_app.urls, add the path to our views

```python
from django.urls import  path
from product_app import views

urlpatterns = [
path('home/', views.home, name = "home"),
]
```
In templates folder, create a 'products' folder and within it a 'base.html' from which all other templates will inherit from. The navbar also contains a conditional statement to ensure that users can only view the details of the app when logged in.

 base.html

```html
{% load static%}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Pharmacy App</title>
    <link rel = "stylesheet" href = {% static 'css/main.css'%}>
     <!-- Raleway font -->
    <link
      href="https://fonts.googleapis.com/css?family=Raleway"
      rel="stylesheet"
    />
    <!-- Montserrat font -->
    <link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark "> 
        <a class="nav-link" href=""><h1 class="navbar-brand" style = "font-size: 25px">PHARM PLUS</h1></a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
          <ul class="nav navbar-nav ml-auto">
           {% if user.is_authenticated%}
              <li class="nav-item">
                <a class="nav-link" href="{% url 'home' %}">HOME</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="{% url 'receipt'%}">RECEIPTS</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="{% url 'all_sales'%}">ALL SALES</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="{% url 'logout'%}">LOGOUT</a>
              </li>
            {% endif %}
          </ul>
     </nav>
    {% block content%}
    {% endblock%}
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>
```
Now we need to create our models. For the project we are going to have three models, a Product model, a Category and a Sale model.

```python
from django.db import models

class Category(models.Model):
    name = models.CharField(max_length = 50, null = True, blank = True)

    def __str__(self):
        return self.name


class Product(models.Model):
    category_name = models.ForeignKey(Category, on_delete = models.CASCADE,null = True, blank = True )
    item_name = models.CharField(max_length = 50, null = True, blank = True)
    total_quantity = models.IntegerField(default = 0, null = True, blank = True)
    issued_quantity = models.IntegerField(default = 0, null = True, blank = True)
    received_quantity = models.IntegerField(default = 0, null = True, blank = True)
    unit_price = models.IntegerField(default = 0, null = True, blank = True)

    def __str__(self):
        return self.item_name


class Sale(models.Model):
    item = models.ForeignKey(Product, on_delete = models.CASCADE)
    quantity = models.IntegerField(default = 0, null = True, blank = True)
    amount_received = models.IntegerField(default = 0, null = True, blank = True)
    issued_to = models.CharField(max_length = 50, null = True, blank = True)
    unit_price = models.IntegerField(default = 0, null = True, blank = True)

    def __str__(self):
        return self.item.item_name
```

Within 'views.py'

```python
from django.shortcuts import render
from product_app.models import Product

def home(request):
    products = Product.objects.all().order_by('-id')

    return render(request,
                  'products/index.html',
                  {'products': products})

```

In 'index.html',
```html
{% extends 'products/base.html'%} {% block content%}
<br></br>

<div class = "container">
  <h1 class= "text-center">ITEMS IN STOCK</h1>
  <br>
  <table class="table">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Category</th>
        <th scope="col">Item Name</th>
        <th scope="col">Quantity</th>
        <th scope="col">Unit Price(₦)</th>
        <th scope = "col">Detail</th>
      </tr>
    </thead>
    {% for product in products%}
    <tbody>
      <tr>    
        <td>{{product.category_name}}</td>
        <td>{{product.item_name}}</td>
        <td>{{product.total_quantity}}</td>
        <td>₦{{product.unit_price}}</td>
        <td><a href="#"
              ><input
                type="submit"
                value="BUY ITEM"
                class="btn btn-secondary btn"
                type="button"
            /></a></td>
      </tr>
    </tbody>
    {% endfor %}
  </table>
</div>
{% endblock%}

```
This is what my app looks now:


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rcxcn4amb160dvx938g2.png)


Next we Build out the product detail page,

In product_app.urls,

```python 
urlpatterns = [
path('home/<int:product_id>/', views.product_detail, name='product_detail'),
]
```

Next, Create a product_detail view:

```python 
 def product_detail(request, product_id):
    product = Product.objects.get(id = product_id)
    return render(request, 
                 'products/product_detail.html',
                 {'product': product})

```

product_detail.html
```html
{% extends 'products/base.html'%} {% block content%}
<br></br>

<div class = "container">
    <a href="{% url 'issue_item' product.id %}" ><input type="submit" value="Order Item" class="btn btn-secondary" btn type="button"/></a>
    <a href="{% url 'add_to_stock' product.id %}" ><input type= "submit" value="Add Item" class="btn btn-secondary btn" type="button"/></a>
</div>

<br></br>
<div class = "container">
  <table class="table">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Category</th>
        <th scope="col">Item Name</th>
        <th scope="col">Quantity</th>
        <th scope="col">Unit Price(₦)</th>   
      </tr>
    </thead>
    <tbody>
      <tr>    
        <td>{{product.category_name}}</td>
        <td>{{product.item_name}}</td>
        <td>{{product.total_quantity}}</td>
        <td>₦{{product.unit_price}}</td>   
      </tr>
    </tbody>  
  </table>
</div>
{% endblock%}

```

Lastly add the 'href' attribute to the button  within the product page that links to the product detail page:

```html
<a href="{% url 'product_detail' product.id %}">
                <input
                type="submit"
                value="BUY ITEM"
                class="btn btn-secondary btn"
                type="button"
                />
</a>
```

My product detail page:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/y995yernk34dzmaqn8d7.png)
 

Now within the product detail page, we want to add two buttons, one for ordering the item and another for replenishing stock. Both lead to different forms.

Within product_detail.html,

```html
<div class = "container">
    <a href="{% url 'issue_item' product.id %}" ><input type="submit" value="Order Item" class="btn btn-secondary" btn type="button"/></a>
    <a href="{% url 'add_to_stock' product.id %}" ><input type= "submit" value="Add Item" class="btn btn-secondary btn" type="button"/></a>
</div>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/orflg47l7g5n7x413tpi.png)


Next we create the url patterns,

```python
urlpatterns = [
path('issue_item/<str:pk>/', views.issue_item, name='issue_item'),   
    path('add_to_stock/<str:pk>/', views.add_to_stock, name='add_to_stock'),
]

```

Now we want to define an add_to_stock form and a sales form. Create a 'forms.py' file within 'product_app'. Next, create an AddForm which uses the 'received_quantity' field earlier defined in our Product model. Finally create a SaleForm that uses the Sale model and inherits the 'quantity, amount_received and issued_to' fields.

```python
from django.forms import ModelForm
from .models import *

class AddForm(ModelForm):
    class Meta:
        model = Product
        fields = ['received_quantity']

class SaleForm(ModelForm):
    class Meta:
        model = Sale
        fields = ["quantity", "amount_received", "issued_to"]
```
Lastly we need to create our views

in views.py
```python

from product_app.forms import AddForm, SaleForm

def issue_item(request, pk):
    issued_item = Product.objects.get(id = pk)
    sales_form = SaleForm(request.POST)  

    if request.method == 'POST':     
        if sales_form.is_valid():
            new_sale = sales_form.save(commit=False)
            new_sale.item = issued_item
            new_sale.unit_price = issued_item.unit_price   
            new_sale.save()
            #To keep track of the stock remaining after sales
            issued_quantity = int(request.POST['quantity'])
            issued_item.total_quantity -= issued_quantity
            issued_item.save()

            return redirect('receipt') 

    return render (request, 'products/issue_item.html',
     {
    'sales_form': sales_form,
    })


def add_to_stock(request, pk):
    issued_item = Product.objects.get(id = pk)
    form = AddForm(request.POST)

    if request.method == 'POST':
        if form.is_valid():
           #To add to the remaining stock quantity is reducing
            added_quantity = 
            int(request.POST['received_quantity'])
            issued_item.total_quantity += added_quantity
            issued_item.save()
            return redirect('home')

    return render (request, 'products/add_to_stock.html', {'form': form})

```

issue.item.html

```html
{% extends 'products/base.html'%} 
{% load crispy_forms_tags%} 
{% load static %}
{% block content%}
<br/>

<div class="container">
  <form method="POST" action = "">
    <h1 class = "text-center
    ">SALES FORM</h1><br>
    {% csrf_token %} 
    {{sales_form | crispy}}
    <input type = "submit" class="btn btn-secondary btn"type="button">
  </form>
</div>
{% endblock %}

```


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/eu6rc9d45x821lf6pvvo.png)


add_to_stock.html

```html
{% extends 'products/base.html'%} 
{% load crispy_forms_tags%} 
{% load static %}
{% block content%}
<br/>

<div class="container">
  <form method="POST" action = "">
    <h1 class = "text-center
    ">SALES FORM</h1><br>
    {% csrf_token %} 
    {{form | crispy}}
    <input type = "submit" class="btn btn-secondary btn"type="button">
  </form>
</div>
{% endblock %}

```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cf2dp1tzsvmnvocvi856.png)

Now we need to build out the receipt page. In urls.py,

```python
urlpatterns = [
path('receipt/', views.receipt, name = "receipt"),
]
```

To carry out the logic for calculating the total cost of each item based on the unit price and the quantity, we need to create a function 'get_total' within our sales model to handle this. Also another function 'get_change' calculates the balance received by each customer by subtracting the total cost from the amount received. Finally, call both functions within our receipt template.

```python
class Sale(models.Model):
    item = models.ForeignKey(Product, on_delete = models.CASCADE)
    quantity = models.IntegerField(default = 0, null = True, blank = True)
    amount_received = models.IntegerField(default = 0, null = True, blank = True)
    issued_to = models.CharField(max_length = 50, null = True, blank = True)
    unit_price = models.IntegerField(default = 0, null = True, blank = True)

    def get_total(self):
        total = self.quantity * self.item.unit_price
        return int(total)
    
    def get_change(self):
        change = self.get_total() - self.amount_received
        return abs(int(change))

    
    def __str__(self):
        return self.item.item_name


```

Within views.py

```python 
def receipt(request): 
    sales = Sale.objects.all().order_by('-id')
    return render(request, 
    'products/receipt.html', 
    {'sales': sales,
    })
```

receipt.html

```html
 {% extends 'products/base.html'%} {% block content%}
<br /><br>
<div class="container">
  <h1 class="card-header text-center">ALL RECEIPTS</h1><br>
  {% for sale in sales %}
  <div class="card">
    <div class="card-body">
      <h3 class="card-title">Customer : {{sale.issued_to | title}}</h3>
      <h6 class="card-text">Item : {{sale.item}}</h6>
      <h6 class="card-text">Amount Paid:  ₦{{ sale.amount_received }}</h6>
      <h6 class="card-text">Quantity: {{sale.quantity }}</h6>
      <h2>Total Price :  ₦{{ sale.get_total }}</h2>
      <div style="flex: 1">
        <h6 class="card-text">Change Collected:  ₦{{ sale.get_change }}</h6>
        <a href="{% url 'receipt_detail' sale.id %}">
          <input
            type="submit"
            value="Final Receipt"
            class="btn btn-danger"
            type="button"
          />
        </a>
      </div>
    </div>
  </div>
  <br />
  {% endfor %}
</div>
{% endblock %} 
```

The receipt page:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c6z0cu3csf0e9qxjsdko.png)


Then lastly,we have a receipt detail page that gives the order summary for each specific item:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/02ekxpykls1wxq9bpasv.png)


We have made great progress so far with our app and now the last part is to create a sales table to keep track and sum up all the total sales made, total amount received and the total change given throughout a particular period in review.

In urls.py,
```python
urlpatterns = [
path('all_sales/', views.all_sales, name = 'all_sales')
]

```

in views.py
```python
def all_sales(request):
    sales = Sale.objects.all()
    total  = sum([items.amount_received for items in sales])
    change = sum([items.get_change() for items in sales])
    net = total - change
    return render(request, 'products/all_sales.html',
     {
     'sales': sales, 
     'total': total,
     'change': change, 
     'net': net,
      })
```

We sum up all the total amount received and total change given within our 'all_sale' method and pass the value into our context.

all_sales.html


```html
{% extends 'products/base.html'%} {% block content%}
<br></br>

<div class = "container">
<h1 class = "text-center">TOTAL SALES MADE</h1><br>
  <table class="table">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Total Amount Received</th>
        <th scope="col">Total Change Given</th>
        <th scope="col">Net Amount</th>
      </tr>
    </thead>  
    <tbody>
      <tr>    
        <td>₦{{total}}</td>
        <td>₦{{change}}</td>
        <td>₦{{net}}</td>
      </tr>
    </tbody>
  </table>
</div>
<br></br>

<div class = "container">
  <table class="table">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Customer name</th>
        <th scope="col">Item Bought</th>
        <th scope="col">Quantity</th>
        <th scope="col">Unit Price(₦)</th>
        <th scope="col">Total Cost</th>
        <th scope="col">Amount Paid</th>
        <th scope="col">Change Collected</th>
      </tr>
    </thead>
    {% for sale in sales %}
    <tbody>
      <tr>    
        <td>{{sale.issued_to | title}}</td>
        <td>{{sale.item | title}}</td>
        <td>{{sale.quantity}}</td>
        <td>₦{{sale.unit_price}}</td>
        <td>₦{{sale.get_total}}</td>
        <td>₦{{sale.amount_received}}</td>
        <td>₦{{sale.get_change}}</td>
      </tr>
    </tbody>
    {% endfor %}
  </table>
</div>
{% endblock%}
``` 


This is a final view of what our sales page looks now. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rb0fdio2rsdvr8nnuna7.png)


You can get the complete code on this url:
https://github.com/yahayakenny/Pharmacy-inventory-manager

Live site: https://pharm-plus.herokuapp.com/

Test the app:
username: "pharmacy"
password: "1234"