Build Inventory System with Ajax, PHP & MySQL

Inventory Management System is a tools for managing inventory data like orders, purchase, sales etc. Generally, desktop based inventory management systems are used to manage inventory data but its limited to that specific system. So the web based systems are more useful than desktop application as the web application can be accessed anywhere we need.

So if you’re looking for solution to development web based inventory management systems, then you’re here at right place. In this tutorial you will learn in detail to develop completed inventory management system using Ajax, PHP and MySQL. You would also like to check Invoice System with PHP & MySQL in which you learn to develop invoice or billing system.

Also, read:

We will cover this tutorial in details to create live example to handle all cases to develop complete inventory system.


Here are the features of this inventory management system

  • Secure encrypted user login to access inventory management system.
  • Dashboard to current inventory details.
  • Manage customer to add new customer, edit and delete customer record.
  • Manage category to add new category, edit and delete category record.
  • Manage brand to add new brand details, edit and delete brand record.
  • Manage product to add new product, view, edit and delete product record.
  • Manage supplier to add new supplier details, edit and delete supplier record.
  • Manage purchase to add make new purchase, edit and delete purchase details.
  • Manage orders to create new orders, edit and delete order orders.

As we will cover this tutorial with live example to build inventory management system with Ajax, PHP & MySQL, so the major files for this example is following.

  • index.php
  • customer.php
  • category.php
  • brand.php
  • product.php
  • supplier.php
  • purchase.php
  • orders.php
  • actions.php
  • Inventory.php

Step1: Create MySQL Database Tables
First we will create MySQL database tables to store inventory data to manage it. We will create ims_product table to store product details.

CREATE TABLE `ims_product` (
  `pid` int(11) NOT NULL,
  `categoryid` int(11) NOT NULL,
  `brandid` int(11) NOT NULL,
  `pname` varchar(300) NOT NULL,
  `model` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `quantity` int(11) NOT NULL,
  `unit` varchar(150) NOT NULL,
  `base_price` double(10,2) NOT NULL,
  `tax` decimal(4,2) NOT NULL,
  `minimum_order` double(10,2) NOT NULL,
  `supplier` int(11) NOT NULL,
  `status` enum('active','inactive') NOT NULL,
  `date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `ims_product`
  ADD PRIMARY KEY (`pid`);
  
ALTER TABLE `ims_product`
  MODIFY `pid` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=211;

We will create ims_supplier table to store supplier details.

CREATE TABLE `ims_supplier` (
  `supplier_id` int(11) NOT NULL,
  `supplier_name` varchar(200) NOT NULL,
  `mobile` varchar(50) NOT NULL,
  `address` text NOT NULL,
  `status` enum('active','inactive') NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `ims_supplier`
  ADD PRIMARY KEY (`supplier_id`);

ALTER TABLE `ims_supplier`
  MODIFY `supplier_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=56;

We will create ims_purchase table to store supplier details.


CREATE TABLE `ims_purchase` (
  `purchase_id` int(11) NOT NULL,
  `supplier_id` varchar(255) NOT NULL,
  `product_id` varchar(255) NOT NULL,
  `quantity` varchar(255) NOT NULL,
  `purchase_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `ims_purchase`
  ADD PRIMARY KEY (`purchase_id`);


ALTER TABLE `ims_purchase`
  MODIFY `purchase_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=579;

We will create ims_order table to store order details.

CREATE TABLE `ims_order` (
  `order_id` int(11) NOT NULL,
  `product_id` varchar(255) NOT NULL,
  `total_shipped` int(11) NOT NULL,
  `customer_id` int(11) NOT NULL,
  `order_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `ims_order`
  ADD PRIMARY KEY (`order_id`);

ALTER TABLE `ims_order`
  MODIFY `order_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=26;

Step2: Include Bootstrap, jQuery and jQuery Datatables Fiels
As we will handle design with Bootstrap, so we will include bootstrap and jQuery files. We will also include jQuery Datatables files as we will display inventory data in Datatables.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="js/jquery.dataTables.min.js"></script>
<script src="js/dataTables.bootstrap.min.js"></script>		
<link rel="stylesheet" href="css/dataTables.bootstrap.min.css" />

Step3: Display Current Inventory
In index.php file, we will create design to display current inventory details in table on dashboard menu.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
						<h3 class="panel-title">Current Inventory</h3>
					</div>						
				</div>
			</div>
			<div class="panel-body">
				<div class="row"><div class="col-sm-12 table-responsive">
					<table id="inventoryDetails" class="table table-bordered table-striped">
						<thead><tr>
							<th>Product</th>      
							<th>Product Code</th>	
							<th>Starting Inventory</th> 
							<th>Inventory Recieved</th> 									
							<th>Inventory Shipped</th>
							<th>Inventory on Hand</th>								
						</tr></thead>
					</table>
				</div></div>
			</div>
		</div>
	</div>
</div>

We will load current inventory details in jQuery Datatables by making Ajax request to action.php and call $inventory->getInventoryDetails() to return data in JSON format to load Datatables.

$(document).ready(function(){
	var inventoryData = $('#inventoryDetails').DataTable({
        "processing":true,
        "serverSide":true,
		"lengthChange": false,
        "order":[],
        "ajax":{
            url:"action.php",
            type:"POST",
			data:{action:'getInventoryDetails'},
			dataType:"json"
        },
		'rowCallback': function(row, data, index){
		if(data[5] < 0){
			$(row).find('td:eq(5)').css({'color':'red', 'font-weight':'bold'});
		} else {
			$(row).find('td:eq(5)').css({'color':'green', 'font-weight':'bold'});
		}
		},
        "pageLength": 10
    });	
});	

In method getInventoryDetails() from class Inventory.php, we will get inventory details and return data as JSON.


public function getInventoryDetails(){		
		$sqlQuery = "SELECT p.pid, p.pname, p.model, p.quantity as product_quantity, s.quantity as recieved_quantity, r.total_shipped
			FROM ".$this->productTable." as p
			LEFT JOIN ".$this->purchaseTable." as s ON s.product_id = p.pid
			LEFT JOIN ".$this->orderTable." as r ON r.product_id = p.pid ";		
		if(isset($_POST['order'])) {
			$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
		} else {
			$sqlQuery .= 'ORDER BY p.pid DESC ';
		}
		if($_POST['length'] != -1) {
			$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
		}		
		$result = mysqli_query($this->dbConnect, $sqlQuery);
		$numRows = mysqli_num_rows($result);
		$inventoryData = array();	
		while( $inventory = mysqli_fetch_assoc($result) ) {
			if(!$inventory['recieved_quantity']) {
				$inventory['recieved_quantity'] = 0;
			}
			if(!$inventory['total_shipped']) {
				$inventory['total_shipped'] = 0;
			}			
			$inventoryInHand = ($inventory['product_quantity'] + $inventory['recieved_quantity']) - $inventory['total_shipped'];		
			$inventoryRow = array();
			$inventoryRow[] = $inventory['pname'];
			$inventoryRow[] = $inventory['model'];
			$inventoryRow[] = $inventory['product_quantity'];
			$inventoryRow[] = $inventory['recieved_quantity'];	
			$inventoryRow[] = $inventory['total_shipped'];
			$inventoryRow[] = $inventoryInHand;			
			$inventoryData[] = $inventoryRow;						
		}
		$output = array(
			"draw"				=>	intval($_POST["draw"]),
			"recordsTotal"  	=>  $numRows,
			"recordsFiltered" 	=> 	$numRows,
			"data"    			=> 	$inventoryData
		);
		echo json_encode($output);		
	}

Step4: Manage Customer
In customer.php, we will create design display customers list. We will create design to add/update customer records with Bootstrap Modal form.

<div class="row">
		<div class="col-lg-12">
			<div class="panel panel-default">
				<div class="panel-heading">
					<div class="row">
						<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
							<h3 class="panel-title">Manage Customer</h3>
						</div>
						<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" align="right">
							<button type="button" name="add" id="addCustomer" 
data-toggle="modal" data-target="#userModal" 
class="btn btn-success btn-xs">Add</button>
						</div>
					</div>					   
					<div class="clear:both"></div>
				</div>
				<div class="panel-body">
					<div class="row">
						<div class="col-sm-12 table-responsive">
							<table id="customerList" class="table table-bordered table-striped">
								<thead>
									<tr>
										<th>ID</th>										
										<th>Name</th>
										<th>Address</th>
										<th>Mobile</th>
										<th>Balance</th>
										<th>Edit</th>
										<th>Delete</th>
									</tr>
								</thead>
							</table>
						</div>
					</div>
				</div>
			</div>
		</div>
        <div id="customerModal" class="modal fade">
        	<div class="modal-dialog">
        		<form method="post" id="customerForm">
        			<div class="modal-content">
						<div class="modal-header">
							<button type="button" 
class="close" data-dismiss="modal">×</button>
							<h4 class="modal-title"><i
 class="fa fa-plus"></i> Add Customer</h4>
						</div>
						<div class="modal-body">
							<div class="form-group">
								<label>Name</label>
								<input type="text" 
name="cname" id="cname" class="form-control" required />
							</div>
							<div class="form-group">
								<label>Mobile</label>
								<input type="number" 
name="mobile" id="mobile" class="form-control" required />
							</div>
							<div class="form-group">
								<label>Balance</label>
								<input 
type="number" name="balance" id="balance" class="form-control" required />
							</div>
							<div class="form-group">
								<label>Address</label>
								<textarea
 name="address" id="address" class="form-control" rows="5" required></textarea>
							</div>
						</div>
						<div class="modal-footer">
							<input type="hidden" name="userid" id="userid" />
							<input type="hidden" name="btn_action" id="btn_action" />
							<input type="submit"
 name="action" id="action" 
class="btn btn-info" value="customerAdd" />
							<button type="button" 
class="btn btn-default" 
data-dismiss="modal">Close</button>
						</div>
					</div>
        		</form>
        	</div>
        </div>	
	</div>	

In customer.js file, will handle functionality to display customer records by making Ajax request to action.php and call method $inventory->getCustomerList(); to load customer data.

var userdataTable = $('#customerList').DataTable({
		"lengthChange": false,
		"processing": true,
		"serverSide": true,
		"order": [],
		"ajax":{
			url:"action.php",
			type:"POST",
			data:{action:'customerList'},
			dataType:"json"
		},
		"columnDefs":[
			{
				"target":[4,5],
				"orderable":false
			}
		],
		"pageLength": 25
	});

In method getCustomerList() from class Inventory.php, we will get customer details and return as JSON data.

public function getCustomerList(){		
	$sqlQuery = "SELECT * FROM ".$this->customerTable." ";
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= '(id LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= '(name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR address LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR mobile LIKE "%'.$_POST["search"]["value"].'%") ';
		$sqlQuery .= 'OR balance LIKE "%'.$_POST["search"]["value"].'%") ';
	}
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY id DESC ';
	}
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$customerData = array();	
	while( $customer = mysqli_fetch_assoc($result) ) {		
		$customerRows = array();
		$customerRows[] = $customer['id'];
		$customerRows[] = $customer['name'];
		$customerRows[] = $customer['address'];			
		$customerRows[] = $customer['mobile'];	
		$customerRows[] = $customer['balance'];	
		$customerRows[] = '<button type="button" 
name="update" id="'.$customer["id"].'" class="btn btn-warning btn-xs update">Update</button>';
		$customerRows[] = '<button type="button" 
name="delete" id="'.$customer["id"].'" class="btn btn-danger btn-xs delete" >Delete</button>';
		$customerData[] = $customerRows;
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$customerData
	);
	echo json_encode($output);
}

Step5: Manage Category
In category.php file, we will handle functionality to display category list, add and update category.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
					<div class="row">
						<h3 class="panel-title">Manage Category</h3>
					</div>
				</div>
				<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6">
					<div class="row" align="right">
						 <button type="button" name="add" 
id="categoryAdd" data-toggle="modal" data-target="#categoryModal" class="btn btn-success btn-xs">Add</button>   		
					</div>
				</div>
				<div style="clear:both"></div>
			</div>
			<div class="panel-body">
				<div class="row">
					<div class="col-sm-12 table-responsive">
						<table id="categoryList" class="table table-bordered table-striped">
							<thead><tr>
								<th>ID</th>
								<th>Category Name</th>
								<th>Status</th>
								<th>Edit</th>
								<th>Delete</th>
							</tr></thead>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>
<div id="categoryModal" class="modal fade">
	<div class="modal-dialog">
		<form method="post" id="categoryForm">
			<div class="modal-content">
				<div class="modal-header">
					<button type="button" class="close" data-dismiss="modal">×</button>
					<h4 class="modal-title"><i class="fa fa-plus"></i> Add Category</h4>
				</div>
				<div class="modal-body">
					<label>Category Name</label>
					<input type="text" name="category" id="category" class="form-control" required />
				</div>
				<div class="modal-footer">
					<input type="hidden" name="categoryId" id="categoryId"/>
					<input type="hidden" name="btn_action" id="btn_action"/>
					<input type="submit" name="action" id="action" class="btn btn-info" value="Add" />
					<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
				</div>
			</div>
		</form>
	</div>
</div>

We will make Ajax request to action.php to call method $inventory->getCategoryList() to display category data.


var categoryData = $('#categoryList').DataTable({
		"lengthChange": false,
		"processing":true,
		"serverSide":true,
		"order":[],
		"ajax":{
			url:"action.php",
			type:"POST",
			data:{action:'categoryList'},
			dataType:"json"
		},
		"columnDefs":[
			{
				"targets":[3, 4],
				"orderable":false,
			},
		],
		"pageLength": 25
	});	

In method getCategoryList(), we will get category data and return as JSON data to display in Datatables.

public function getCategoryList(){		
	$sqlQuery = "SELECT * FROM ".$this->categoryTable." ";
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= 'WHERE (name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR status LIKE "%'.$_POST["search"]["value"].'%") ';			
	}
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY categoryid DESC ';
	}
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$categoryData = array();	
	while( $category = mysqli_fetch_assoc($result) ) {		
		$categoryRows = array();
		$status = '';
		if($category['status'] == 'active')	{
			$status = '<span class="label label-success">Active</span>';
		} else {
			$status = '<span class="label label-danger">Inactive</span>';
		}
		$categoryRows[] = $category['categoryid'];
		$categoryRows[] = $category['name'];
		$categoryRows[] = $status;			
		$categoryRows[] = '<button type="button" name="update" 
id="'.$category["categoryid"].'" class="btn btn-warning btn-xs update">Update</button>';
		$categoryRows[] = '<button type="button" name="delete"
 id="'.$category["categoryid"].'" class="btn btn-danger btn-xs delete" >Delete</button>';
		$categoryData[] = $categoryRows;
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$categoryData
	);
	echo json_encode($output);
}

Step6: Manage Brand
In brand.php file, we will handle functionality to display brand list, add new brand, update existing brand details and delete brand.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-md-10">
						<h3 class="panel-title">Manage Brand</h3>
					</div>
					<div class="col-md-2" align="right">
						<button type="button" name="add" 
id="addBrand" class="btn btn-success btn-xs">Add</button>
					</div>
				</div>
			</div>
			<div class="panel-body">
				<table id="brandList" class="table table-bordered table-striped">
					<thead>
						<tr>
							<th>ID</th>
							<th>Category</th>
							<th>Brand Name</th>
							<th>Status</th>
							<th>Edit</th>
							<th>Delete</th>
						</tr>
					</thead>
				</table>
			</div>
		</div>
	</div>
</div>
<div id="brandModal" class="modal fade">
	<div class="modal-dialog">
		<form method="post" id="brandForm">
			<div class="modal-content">
				<div class="modal-header">
					<button type="button" class="close" data-dismiss="modal">×</button>
					<h4 class="modal-title"><i 
class="fa fa-plus"></i> Add Brand</h4>
				</div>
				<div class="modal-body">
					<div class="form-group">
						<select name="categoryid" id="categoryid" class="form-control" required>
							<option value="">Select Category</option>
							<?php echo $inventory->categoryDropdownList(); ?>
						</select>
					</div>
					<div class="form-group">
						<label>Enter Brand Name</label>
						<input type="text" name="bname" id="bname" class="form-control" required />
					</div>
				</div>
				<div class="modal-footer">
					<input type="hidden" name="id" id="id" />
					<input type="hidden" name="btn_action" id="btn_action" />
					<input type="submit" name="action" id="action" class="btn btn-info" value="Add" />
					<button type="button"
 class="btn btn-default" data-dismiss="modal">Close</button>
				</div>
			</div>
		</form>
	</div>
</div>

We will make Ajax request action.php to load brand data in jQuery datatables by calling $inventory->getBrandList() method.

var branddataTable = $('#brandList').DataTable({
		"lengthChange": false,
		"processing":true,
		"serverSide":true,
		"order":[],
		"ajax":{
			url:"action.php",
			type:"POST",
			data:{action:'listBrand'},
			dataType:"json"
		},
		"columnDefs":[
			{
				"targets":[4, 5],
				"orderable":false,
			},
		],
		"pageLength": 10
	});

In method getBrandList() from class Inventory.php, we will get brand list and return as JSON data.

public function getBrandList(){				
	$sqlQuery = "SELECT * FROM ".$this->brandTable." as b 
		INNER JOIN ".$this->categoryTable." as c ON c.categoryid = b.categoryid ";
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= 'WHERE b.bname LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR c.name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR b.status LIKE "%'.$_POST["search"]["value"].'%" ';		
	}
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY b.id DESC ';
	}
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$brandData = array();	
	while( $brand = mysqli_fetch_assoc($result) ) {			
		$status = '';
		if($brand['status'] == 'active')	{
			$status = '<span class="label label-success">Active</span>';
		} else {
			$status = '<span class="label label-danger">Inactive</span>';
		}
		$brandRows = array();
		$brandRows[] = $brand['id'];
		$brandRows[] = $brand['bname'];
		$brandRows[] = $brand['name'];
		$brandRows[] = $status;
		$brandRows[] = '<button type="button" name="update" 
id="'.$brand["id"].'" class="btn btn-warning btn-xs update">Update</button>';
		$brandRows[] = '<button type="button" name="delete" 
id="'.$brand["id"].'" class="btn btn-danger btn-xs delete" data-status="'.$brand["status"].'">Delete</button>';
		$brandData[] = $brandRows;
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$brandData
	);
	echo json_encode($output);
}

Step7: Manage Product
In product.php, we will handle functionality to list product, add new product, update product details and delete product.


<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
						<h3 class="panel-title">Manage Product</h3>
					</div>                        
					<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" 
align='right'>
						<button type="button" name="add" 
id="addProduct" 
class="btn btn-success btn-xs">Add</button>
					</div>
				</div>
			</div>
			<div class="panel-body">
				<div class="row"><div 
class="col-sm-12 table-responsive">
					<table id="productList" 
class="table table-bordered table-striped">
						<thead><tr>
							<th>ID</th>      
							<th>Category</th>	
							<th>Brand Name</th>									
							<th>Product Name</th>
							<th>Product Model</th>
							<th>Quantity</th>
							<th>Supplier Name</th>
							<th>Status</th>
							<th></th>
							<th></th>
							<th></th>
						</tr></thead>
					</table>
				</div></div>
			</div>
		</div>
	</div>
</div>
<div id="productModal" class="modal fade">
	<div class="modal-dialog">
		<form method="post" id="productForm">
			<div class="modal-content">
				<div class="modal-header">
					<button type="button" 
class="close" data-dismiss="modal">×</button>
					<h4 class="modal-title"><i 
class="fa fa-plus"></i> Add Product</h4>
				</div>
				<div class="modal-body">
					<div class="form-group">
						<label>Select Category</label>
						<select name="categoryid" id="categoryid" class="form-control" required>
							<option value="">Select Category</option>
							<?php echo $inventory->categoryDropdownList();?>
						</select>
					</div>
					<div class="form-group">
						<label>Select Brand</label>
						<select name="brandid" id="brandid" class="form-control" required>
							<option value="">Select Brand</option>
						</select>
					</div>
					<div class="form-group">
						<label>Product Name</label>
						<input type="text" name="pname" id="pname" class="form-control" required />
					</div>
					<div class="form-group">
						<label>Product Model</label>
						<input type="text" name="pmodel" 
id="pmodel" class="form-control" required />
					</div>
					<div class="form-group">
						<label>Product Description</label>
						<textarea 
name="description" 
id="description" class="form-control" 
rows="5" required></textarea>
					</div>
					<div class="form-group">
						<label>Product Quantity</label>
						<div class="input-group">
							<input type="text"
 name="quantity" 
id="quantity" class="form-control" required pattern="[+-]?([0-9]*[.])?[0-9]+" /> 
							<span class="input-group-addon">
								<select name="unit" id="unit" required>
									<option value="">Select Unit</option>
									<option value="Bags">Bags</option>
									<option value="Bottles">Bottles</option>
									<option value="Box">Box</option>
									<option value="Dozens">Dozens</option>
									<option value="Feet">Feet</option>
									<option value="Gallon">Gallon</option>
									<option value="Grams">Grams</option>
									<option value="Inch">Inch</option>
									<option value="Kg">Kg</option>
									<option value="Liters">Liters</option>
									<option value="Meter">Meter</option>
									<option value="Nos">Nos</option>
									<option value="Packet">Packet</option>
									<option value="Rolls">Rolls</option>
								</select>
							</span>
						</div>
					</div>
					<div class="form-group">
						<label>Product Base Price</label>
						<input type="text" name="base_price" 
id="base_price" class="form-control" required pattern="[+-]?([0-9]*[.])?[0-9]+" />
					</div>
					<div class="form-group">
						<label>Product Tax (%)</label>
						<input type="text" name="tax" id="tax" class="form-control" required pattern="[+-]?([0-9]*[.])?[0-9]+" />
					</div>
					<div class="form-group">
						<label>Supplier</label>
						<select name="supplierid" id="supplierid" class="form-control" required>
							<option value="">Select Supplier</option>
							<?php echo $inventory->supplierDropdownList();?>
						</select>
					</div>
				</div>
				<div class="modal-footer">
					<input type="hidden" name="pid" id="pid" />
					<input type="hidden" name="btn_action" id="btn_action" />
					<input type="submit" name="action" id="action" class="btn btn-info" value="Add" />
					<button type="button" 
class="btn btn-default" 
data-dismiss="modal">Close</button>
				</div>
			</div>
		</form>
	</div>
</div>

We will make Ajax request to method $inventory->getProductList() to get product list.

var productData = $('#productList').DataTable({
		"lengthChange": false,
        "processing":true,
        "serverSide":true,
        "order":[],
        "ajax":{
            url:"action.php",
            type:"POST",
			data:{action:'listProduct'},
			dataType:"json"
        },
        "columnDefs":[
            {
                "targets":[7, 8, 9],
                "orderable":false,
            },
        ],
        "pageLength": 10
    });

In method getProductList(), we will get product details and return as JSON data.

public function getProductList(){				
	$sqlQuery = "SELECT * FROM ".$this->productTable." as p
		INNER JOIN ".$this->brandTable." as b ON b.id = p.brandid
		INNER JOIN ".$this->categoryTable." as c ON c.categoryid = p.categoryid 
		INNER JOIN ".$this->supplierTable." as s ON s.supplier_id = p.supplier ";
	if(isset($_POST["search"]["value"])) {
		$sqlQuery .= 'WHERE b.bname LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR c.name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR p.pname LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR p.quantity LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR s.supplier_name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= 'OR p.pid LIKE "%'.$_POST["search"]["value"].'%" ';
	}
	if(isset($_POST['order'])) {
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY p.pid DESC ';
	}
	if($_POST['length'] != -1) {
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}		
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$productData = array();	
	while( $product = mysqli_fetch_assoc($result) ) {			
		$status = '';
		if($product['status'] == 'active') {
			$status = '<span class="label label-success">Active</span>';
		} else {
			$status = '<span class="label label-danger">Inactive</span>';
		}
		$productRow = array();
		$productRow[] = $product['pid'];
		$productRow[] = $product['name'];
		$productRow[] = $product['bname'];
		$productRow[] = $product['pname'];	
		$productRow[] = $product['model'];			
		$productRow[] = $product["quantity"];
		$productRow[] = $product['supplier_name'];
		$productRow[] = $status;
		$productRow[] = '<button type="button" name="view" 
id="'.$product["pid"].'" class="btn btn-info btn-xs view">View</button>';
		$productRow[] = '<button type="button" name="update" 
id="'.$product["pid"].'" class="btn btn-warning btn-xs update">Update</button>';
		$productRow[] = '<button type="button" name="delete" 
id="'.$product["pid"].'" class="btn btn-danger btn-xs delete" 
data-status="'.$product["status"].'">Delete</button>';
		$productData[] = $productRow;						
	}
	$outputData = array(
		"draw"    			=> 	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$productData
	);
	echo json_encode($outputData);
}

Step8: Manage Supplier
In supplier.php, we will design page to handle functionality to display supplier list, add, update and delete suppliers.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
						<h3 class="panel-title">Manage Supplier</h3>
					</div>
					<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" align="right">
						<button type="button" name="add"
 id="addSupplier" data-toggle="modal" data-target="#userModal" class="btn btn-success btn-xs">Add</button>
					</div>
				</div>					   
				<div class="clear:both"></div>
			</div>
			<div class="panel-body">
				<div class="row">
					<div class="col-sm-12 table-responsive">
						<table id="supplierList"
 class="table table-bordered table-striped">
							<thead>
								<tr>
									<th>ID</th>										
									<th>Name</th>
									<th>Mobile</th>
									<th>Address</th>
									<th>Status</th>										
									<th>Edit</th>
									<th>Delete</th>
								</tr>
							</thead>
						</table>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div id="supplierModal" class="modal fade">
		<div class="modal-dialog">
			<form method="post" id="supplierForm">
				<div class="modal-content">
					<div class="modal-header">
						<button type="button" 
class="close" data-dismiss="modal">×</button>
						<h4 class="modal-title"><i class="fa fa-plus"></i> Add Supplier</h4>
					</div>
					<div class="modal-body">
						<div class="form-group">
							<label>Supplier Name</label>
							<input type="text" 
name="supplier_name" id="supplier_name" 
class="form-control" required />
						</div>	
						<div class="form-group">
							<label>Mobile</label>
							<input type="text" name="mobile" id="mobile" class="form-control" required />
						</div>								
						<div class="form-group">
							<label>Address</label>
							<textarea name="address" 
id="address" class="form-control" rows="5" required></textarea>
						</div>
					</div>
					<div class="modal-footer">
						<input type="hidden" name="supplier_id" id="supplier_id" />
						<input type="hidden" name="btn_action" id="btn_action" />
						<input type="submit" 
name="action" id="action" 
class="btn btn-info" value="addSupplier" />
						<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
					</div>
				</div>
			</form>
		</div>
	</div>	
</div>

We will make Ajax request on page load to display suppliers list. We will call inventory method $inventory->getSupplierList() to get suppliers data.

var supplierDataTable = $('#supplierList').DataTable({
		"lengthChange": false,
		"processing": true,
		"serverSide": true,
		"order": [],
		"ajax":{
			url:"action.php",
			type:"POST",
			data:{action:'supplierList'},
			dataType:"json"
		},
		"columnDefs":[
			{
				"target":[4,5],
				"orderable":false
			}
		],
		"pageLength": 25
	});

In method getSupplierList(), we will get suppliers data from MySQL table and return as JSON data.

public function getSupplierList(){		
	$sqlQuery = "SELECT * FROM ".$this->supplierTable." ";
	if(!empty($_POST["search"]["value"])){
		$sqlQuery .= 'WHERE (supplier_name LIKE "%'.$_POST["search"]["value"].'%" ';
		$sqlQuery .= '(address LIKE "%'.$_POST["search"]["value"].'%" ';			
	}
	if(!empty($_POST["order"])){
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY supplier_id DESC ';
	}
	if($_POST["length"] != -1){
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}	
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$supplierData = array();	
	while( $supplier = mysqli_fetch_assoc($result) ) {	
		$status = '';
		if($supplier['status'] == 'active') {
			$status = '<span class="label label-success">Active</span>';
		} else {
			$status = '<span class="label label-danger">Inactive</span>';
		}
		$supplierRows = array();
		$supplierRows[] = $supplier['supplier_id'];		
		$supplierRows[] = $supplier['supplier_name'];	
		$supplierRows[] = $supplier['mobile'];			
		$supplierRows[] = $supplier['address'];	
		$supplierRows[] = $status;			
		$supplierRows[] = '<button type="button" name="update" id="'.$supplier["supplier_id"].'" 
class="btn btn-warning btn-xs update">Update</button>';
		$supplierRows[] = '<button type="button" name="delete" id="'.$supplier["supplier_id"].'" 
class="btn btn-danger btn-xs delete" >Delete</button>';
		$supplierData[] = $supplierRows;
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$supplierData
	);
	echo json_encode($output);
}

Step9: Manage Purchase
In purchase.php, we will design page to handle purchase functionality like list purchase, make new purchase, update purchase details and delete purchase.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
						<h3 class="panel-title">Manage Purchase</h3>
					</div>                        
					<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" align='right'>
						<button type="button" name="addPurchase" 
id="addPurchase" class="btn btn-success btn-xs">Add</button>
					</div>
				</div>
			</div>
			<div class="panel-body">
				<div class="row"><div class="col-sm-12 table-responsive">
					<table id="purchaseList" class="table table-bordered table-striped">
						<thead><tr>
							<th>ID</th> 									
							<th>Product</th>	
							<th>Quantity</th>	
							<th>Supplier</th>                                           
							<th></th>
							<th></th>
						</tr></thead>
					</table>
				</div></div>
			</div>
		</div>
	</div>
</div>
<div id="purchaseModal" class="modal fade">
	<div class="modal-dialog">
		<form method="post" id="purchaseForm">
			<div class="modal-content">
				<div class="modal-header">
					<button type="button" class="close" 
data-dismiss="modal">×</button>
					<h4 class="modal-title"><i class="fa fa-plus"></i> Add Purchase</h4>
				</div>
				<div class="modal-body">                           
					<div class="form-group">
						<label>Product Name</label>
						<select name="product" id="product" class="form-control" required>
							<option value="">Select Product</option>
							<?php echo $inventory->productDropdownList();?>
						</select>
					</div>	                           
					<div class="form-group">
						<label>Product Quantity</label>
						<div class="input-group">
							<input type="text"
 name="quantity" id="quantity" class="form-control" required pattern="[+-]?([0-9]*[.])?[0-9]+" />        
						</div>
					</div>                           
					<div class="form-group">
						<label>Supplier</label>
						<select name="supplierid" id="supplierid" class="form-control" required>
							<option value="">Select Supplier</option>
							<?php echo $inventory->supplierDropdownList();?>
						</select>
					</div>
				</div>
				<div class="modal-footer">
					<input type="hidden" name="purchase_id" id="purchase_id" />
					<input type="hidden" name="btn_action" id="btn_action" />
					<input type="submit" name="action" id="action" class="btn btn-info" value="Add" />
					<button type="button" 
class="btn btn-default" 
data-dismiss="modal">Close</button>
				</div>
			</div>
		</form>
	</div>
</div>

We will make Ajax request to inventory method $inventory->listPurchase() to load purchase data to datatables.

var purchaseData = $('#purchaseList').DataTable({
		"lengthChange": false,
        "processing":true,
        "serverSide":true,
        "order":[],
        "ajax":{
            url:"action.php",
            type:"POST",
			data:{action:'listPurchase'},
			dataType:"json"
        },
        "pageLength": 10
    });

In method listPurchase(), we will get purchase data from MySQL tables and return as JSON data.

public function listPurchase(){		
	$sqlQuery = "SELECT * FROM ".$this->purchaseTable." as ph
		INNER JOIN ".$this->productTable." as p ON p.pid = ph.product_id 
		INNER JOIN ".$this->supplierTable." as s ON s.supplier_id = ph.supplier_id ";
	if(isset($_POST['order'])) {
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY ph.purchase_id DESC ';
	}
	if($_POST['length'] != -1) {
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}		
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$purchaseData = array();	
	while( $purchase = mysqli_fetch_assoc($result) ) {			
		$productRow = array();
		$productRow[] = $purchase['purchase_id'];
		$productRow[] = $purchase['pname'];
		$productRow[] = $purchase['quantity'];			
		$productRow[] = $purchase['supplier_name'];			
		$productRow[] = '<button type="button" name="update" 
id="'.$purchase["purchase_id"].'" class="btn btn-warning btn-xs update">Update</button>';
		$productRow[] = '<button type="button" name="delete" 
id="'.$purchase["purchase_id"].'" class="btn btn-danger btn-xs delete">Delete</button>';
		$purchaseData[] = $productRow;						
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$purchaseData
	);
	echo json_encode($output);		
}

Step10: Manage Orders
In order.php, we will design page and handle functionality to list orders, add new order, update order and delete order.

<div class="row">
	<div class="col-lg-12">
		<div class="panel panel-default">
			<div class="panel-heading">
				<div class="row">
					<div class="col-lg-10 col-md-10 col-sm-8 col-xs-6">
						<h3 class="panel-title">Manage Orders</h3>
					</div>                        
					<div class="col-lg-2 col-md-2 col-sm-4 col-xs-6" align='right'>
						<button type="button" name="add" 
id="addOrder" class="btn btn-success btn-xs">Add</button>
					</div>
				</div>
			</div>
			<div class="panel-body">
				<div class="row"><div class="col-sm-12 table-responsive">
					<table id="orderList" class="table table-bordered table-striped">
						<thead><tr>
							<th>ID</th>      
							<th>Product</th>	
							<th>Total Item</th> 
							<th>Customer</th> 									
							<th></th>
							<th></th>
						</tr></thead>
					</table>
				</div></div>
			</div>
		</div>
	</div>
</div>
<div id="orderModal" class="modal fade">
	<div class="modal-dialog">
		<form method="post" id="orderForm">
			<div class="modal-content">
				<div class="modal-header">
					<button type="button" class="close" data-dismiss="modal">×</button>
					<h4 class="modal-title"><i 
class="fa fa-plus"></i> Add Order</h4>
				</div>
				<div class="modal-body">
					<div class="form-group">
						<label>Product Name</label>
						<select name="product" id="product" class="form-control" required>
							<option value="">Select Product</option>
							<?php echo $inventory->productDropdownList();?>
						</select>
					</div>
					 <div class="form-group">
						<label>Total Item</label>
						<div class="input-group">
							<input type="text" name="shipped" id="shipped" class="form-control" required />        
						</div>
					</div> 
					<div class="form-group">
						<label>Customer Name</label>
						<select name="customer" id="customer" class="form-control" required>
							<option value="">Select Customer</option>
							<?php echo $inventory->customerDropdownList();?>
						</select>
					</div>	
				</div>
				<div class="modal-footer">
					<input type="hidden" name="order_id" id="order_id" />
					<input type="hidden" name="btn_action" id="btn_action" />
					<input type="submit" name="action" id="action" class="btn btn-info" value="Add" />
					<button type="button" 
class="btn btn-default" data-dismiss="modal">Close</button>
				</div>
			</div>
		</form>
	</div>
</div>

We will make Ajax request to load orders datatable by calling inventory method $inventory->listOrders() to load data.

var orderData = $('#orderList').DataTable({
		"lengthChange": false,
        "processing":true,
        "serverSide":true,
        "order":[],
        "ajax":{
            url:"action.php",
            type:"POST",
			data:{action:'listOrder'},
			dataType:"json"
        },
        "pageLength": 10
    });

In method listOrders(), we will get orders details from MySQL database tables and return as JSON data.

public function listOrders(){		
	$sqlQuery = "SELECT * FROM ".$this->orderTable." as o
		INNER JOIN ".$this->customerTable." as c ON c.id = o.customer_id
		INNER JOIN ".$this->productTable." as p ON p.pid = o.product_id ";		
	if(isset($_POST['order'])) {
		$sqlQuery .= 'ORDER BY '.$_POST['order']['0']['column'].' '.$_POST['order']['0']['dir'].' ';
	} else {
		$sqlQuery .= 'ORDER BY o.order_id DESC ';
	}
	if($_POST['length'] != -1) {
		$sqlQuery .= 'LIMIT ' . $_POST['start'] . ', ' . $_POST['length'];
	}		
	$result = mysqli_query($this->dbConnect, $sqlQuery);
	$numRows = mysqli_num_rows($result);
	$orderData = array();	
	while( $order = mysqli_fetch_assoc($result) ) {			
		$orderRow = array();
		$orderRow[] = $order['order_id'];
		$orderRow[] = $order['pname'];
		$orderRow[] = $order['total_shipped'];	
		$orderRow[] = $order['name'];			
		$orderRow[] = '<button type="button" name="update" 
id="'.$order["order_id"].'" class="btn btn-warning btn-xs update">Update</button>';
		$orderRow[] = '<button type="button" name="delete" 
id="'.$order["order_id"].'" class="btn btn-danger btn-xs delete">Delete</button>';
		$orderData[] = $orderRow;						
	}
	$output = array(
		"draw"				=>	intval($_POST["draw"]),
		"recordsTotal"  	=>  $numRows,
		"recordsFiltered" 	=> 	$numRows,
		"data"    			=> 	$orderData
	);
	echo json_encode($output);		
}

There are functionality handled to add, edit and delete functionality to manage inventory details. You need to download script to get complete code and database tables.

You may also like:

You can view the live demo from the Demo link and can download the full script from the Download link below.
Demo Download

32 thoughts on “Build Inventory System with Ajax, PHP & MySQL

  1. Hi There and thank you for this gem of a code!
    I have a question… maybe a stupid one but I am struggling a bit with adding images here, like photos of the contacts or employees. How do you suggest we do that here? for some reason the $_FILES attribute is not working in Inventory.php when I want to insert into the db

    Best Regards and thank you once again!

    1. You need to handle file upload through ajax using FormData() to get into $_FILES attribute. Thanks!

  2. Hello,

    The paginalist does not work. No more pages (products) will be displayed if there are more than 10 entries.

    I do not see what’s wrong, can you help?

    PS: thank you very much for sharing van de code.

      1. Great tutorial!! However, also having an issue with pagination, so on table sort (to check IDs) table fails.

        1. Sorry I could not edit last reply… “table crash” was empty results when using sort on ID column only (every table has that issue) ..I could not resolve this.
          Datatables code looks correct..maybe something in AJAX results on that “id” column?
          Also, I never got the login working, seems like I had the same issue on the Invoice tutorial as well. Anyhow, Datatables on Invoice tutorial works, so I think I will just build off of it. I would like to hear if you can resolve the Inventory for me..but if I don’t, I want to say how much I love your code structure and organization..the tutorials help me so much!! thanks!!

  3. Hi, very nice application. I am working through it to get a better understanding of how you have built the various components but I have noticed that the source code download link is no longer available? Could you advise how I can get the source code?

    1. The download link is at the end of tutorial and locked. You need to tutorial on social network get unlock download link. thanks!

  4. below the error message coming in testing level
    Warning: Use of undefined constant MYSQL_ASSOC – assumed ‘MYSQL_ASSOC’ (this will throw an Error in a future version of PHP) in C:\xampp\htdocs\inventorysystem\Inventory.php on line 33

    Warning: mysqli_fetch_array() expects parameter 2 to be int, string given in C:\xampp\htdocs\inventorysystem\Inventory.php on line 33

  5. Hi, great work you get going here. Am learning a lot from ur piece. Adding a customer does not work for me. I enter my data click the add and nothing happens, no error, no entry into the database. What do you think is causing this. Will appreciate ur view here. Thanks

  6. Hi I loved this project but I can I extract some of the pages from it for example I dont want supplier page is it possible ?

  7. As per your demo update button will not work when you click this add box willopen not edit box I try to change but it won’t work can you please help me

    1. there was some issue, I have update project file. you can download it and use that. thanks!

    1. I have updated database tables details in tutorial, you can alter as per details. then it should work. thanks!

  8. Hello,
    Thanks for good script. Suddenly the contents (for Products) of an existing table are no longer displayed to me. When I add new products, they are displayed to me. But unfortunately not the existing content. The other tables are displayed normally. I didn’t adjust anything, before that everything worked very well. Where’s the problem?

    1. Try to debug your code, may be there any error. you can also send your code to us to fix issue. thanks!

Comments are closed.