Creating an advanced-level Supply Chain Tracking System involves designing a robust database structure, implementing backend logic, and creating responsive frontend pages using Flask and Bootstrap 5. Below is a detailed breakdown of the database structure, Flask application code, and related pages.
Database Structure
The database will store information about suppliers, manufacturers, distributors, retailers, products, shipments, and tracking data. We'll use SQLAlchemy (ORM for Flask) to define the database models.
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class Supplier(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
address = db.Column(db.String(200), nullable=False)
contact = db.Column(db.String(100), nullable=False)
products = db.relationship('Product', backref='supplier', lazy=True)
class Manufacturer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
address = db.Column(db.String(200), nullable=False)
contact = db.Column(db.String(100), nullable=False)
products = db.relationship('Product', backref='manufacturer', lazy=True)
class Distributor(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
address = db.Column(db.String(200), nullable=False)
contact = db.Column(db.String(100), nullable=False)
shipments = db.relationship('Shipment', backref='distributor', lazy=True)
class Retailer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
address = db.Column(db.String(200), nullable=False)
contact = db.Column(db.String(100), nullable=False)
shipments = db.relationship('Shipment', backref='retailer', lazy=True)
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=False)
supplier_id = db.Column(db.Integer, db.ForeignKey('supplier.id'), nullable=False)
manufacturer_id = db.Column(db.Integer, db.ForeignKey('manufacturer.id'), nullable=False)
shipments = db.relationship('Shipment', backref='product', lazy=True)
class Shipment(db.Model):
id = db.Column(db.Integer, primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
distributor_id = db.Column(db.Integer, db.ForeignKey('distributor.id'), nullable=False)
retailer_id = db.Column(db.Integer, db.ForeignKey('retailer.id'), nullable=False)
shipment_date = db.Column(db.DateTime, default=datetime.utcnow)
tracking_data = db.relationship('TrackingData', backref='shipment', lazy=True)
class TrackingData(db.Model):
id = db.Column(db.Integer, primary_key=True)
shipment_id = db.Column(db.Integer, db.ForeignKey('shipment.id'), nullable=False)
location = db.Column(db.String(100), nullable=False)
status = db.Column(db.String(100), nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
Flask Application Structure
Here’s the directory structure for the project:
supply_chain_tracking/
│
├── app/
│ ├── __init__.py # Initialize the Flask app and database
│ ├── models.py # Database models (Supplier, Manufacturer, Distributor, Retailer, Product, Shipment, TrackingData)
│ ├── routes.py # Application routes and views
│ ├── forms.py # Forms for user input (if using Flask-WTF)
│ ├── static/ # Static files (CSS, JS, images)
│ │ ├── css/
│ │ │ └── styles.css # Custom CSS styles
│ │ └── js/
│ │ └── scripts.js # Custom JavaScript files
│ └── templates/ # HTML templates
│ ├── register.html # Registration page
│ ├── login.html # Login page
│ ├── dashboard.html # User dashboard
│ ├── product_details.html # Product details page
│ ├── shipments.html # Shipments overview page
│ └── layout.html # Base layout for templates
│
├── migrations/ # Database migration files (if using Flask-Migrate)
│
├── config.py # Configuration settings for the app
│
├── requirements.txt # Python package dependencies
│
└── run.py # Entry point to run the application
Flask Application Code
Below is the Flask application code with routes, forms, and database integration.
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///supply_chain.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# User Registration
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = generate_password_hash(request.form['password'], method='sha256')
new_user = User(username=username, email=email, password=password)
db.session.add(new_user)
db.session.commit()
flash('Registration successful! Please log in.', 'success')
return redirect(url_for('login'))
return render_template('register.html')
# User Login
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
session['user_id'] = user.id
session['username'] = user.username
flash('Login successful!', 'success')
return redirect(url_for('dashboard'))
else:
flash('Invalid email or password.', 'danger')
return render_template('login.html')
# Dashboard
@app.route('/')
def dashboard():
if 'user_id' not in session:
return redirect(url_for('login'))
products = Product.query.all()
return render_template('dashboard.html', products=products)
# Product Details
@app.route('/product/<int:id>')
def product_details(id):
product = Product.query.get_or_404(id)
shipments = Shipment.query.filter_by(product_id=id).all()
return render_template('product_details.html', product=product, shipments=shipments)
# Add Shipment
@app.route('/add_shipment', methods=['POST'])
def add_shipment():
product_id = request.form.get('product_id', type=int)
distributor_id = request.form.get('distributor_id', type=int)
retailer_id = request.form.get('retailer_id', type=int)
new_shipment = Shipment(product_id=product_id, distributor_id=distributor_id, retailer_id=retailer_id)
db.session.add(new_shipment)
db.session.commit()
flash('Shipment added successfully!', 'success')
return redirect(url_for('dashboard'))
# View Shipments
@app.route('/shipments')
def view_shipments():
shipments = Shipment.query.all()
return render_template('shipments.html', shipments=shipments)
# User Logout
@app.route('/logout')
def logout():
session.pop('user_id', None)
session.pop('username', None)
flash('You have been logged out.', 'success')
return redirect(url_for('dashboard'))
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
HTML Templates
Here are some basic HTML templates using Bootstrap 5 for the pages mentioned.
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Register</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Register</h2>
<form method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Login</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Login</h2>
<form method="POST">
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
dashboard.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Dashboard</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Supply Chain Tracker</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/shipments">View Shipments</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>Available Products</h2>
<div class="row">
{% for product in products %}
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">{{ product.name }}</h5>
<p class="card-text">{{ product.description }}</p>
<form action="{{ url_for('add_shipment') }}" method="POST">
<input type="hidden" name="product_id" value="{{ product.id }}">
<div class="mb-3">
<label for="distributor_id" class="form-label">Distributor ID</label>
<input type="number" class="form-control" name="distributor_id" required>
</div>
<div class="mb-3">
<label for="retailer_id" class="form-label">Retailer ID</label>
<input type="number" class="form-control" name="retailer_id" required>
</div>
<button type="submit" class="btn btn-primary">Add Shipment</button>
</form>
<a href="{{ url_for('product_details', id=product.id) }}" class="btn btn-info mt-2">View Details</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
product_details.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>{{ product.name }} Details</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Supply Chain Tracker</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/shipments">View Shipments</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>{{ product.name }}</h2>
<p>{{ product.description }}</p>
<h4>Shipments</h4>
<ul class="list-group">
{% for shipment in shipments %}
<li class="list-group-item">
Shipment ID: {{ shipment.id }} - Distributor ID: {{ shipment.distributor_id }} - Retailer ID: {{ shipment.retailer_id }} - Date: {{ shipment.shipment_date.strftime('%Y-%m-%d') }}
</li>
{% endfor %}
</ul>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
shipments.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Shipments</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Supply Chain Tracker</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/dashboard">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>All Shipments</h2>
{% if shipments %}
<table class="table">
<thead>
<tr>
<th>Shipment ID</th>
<th>Product ID</th>
<th>Distributor ID</th>
<th>Retailer ID</th>
<th>Shipment Date</th>
</tr>
</thead>
<tbody>
{% for shipment in shipments %}
<tr>
<td>{{ shipment.id }}</td>
<td>{{ shipment.product_id }}</td>
<td>{{ shipment.distributor_id }}</td>
<td>{{ shipment.retailer_id }}</td>
<td>{{ shipment.shipment_date.strftime('%Y-%m-%d') }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No shipments found.</p>
{% endif %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Additional Features and Enhancements
To further enhance the Supply Chain Tracking System, consider implementing the following features:
- Real-time Tracking: Integrate a real-time tracking system for shipments using GPS or third-party APIs.
- User Roles: Implement different user roles (e.g., admin, supplier, distributor) with specific permissions.
- Reporting: Create reports for shipments, product availability, and supplier performance.
- Notifications: Set up email or SMS notifications for shipment status updates.
- Analytics Dashboard: Provide analytics on supply chain performance, including delays and bottlenecks.
Conclusion
This advanced Supply Chain Tracking System structure provides a comprehensive foundation for building a fully functional application using Flask and Bootstrap 5. You can further enhance the application by integrating real-time tracking, implementing user roles, and adding reporting features. The modular design allows for easy expansion and maintenance, making it suitable for both beginners and experienced developers.