# Dashboard Implementation Plan for Django Manufacturing App ## Overview This document outlines the implementation plan for the dashboard module, including data visualization, widgets, and printable functionality. ## Dashboard Models ### 1. Dashboard Widget Model ```python # dashboard/models.py from django.db import models from django.contrib.auth.models import User class DashboardWidget(models.Model): WIDGET_TYPES = [ ('chart', 'Chart'), ('table', 'Table'), ('kpi', 'Key Performance Indicator'), ('summary', 'Summary'), ('list', 'List'), ] name = models.CharField(max_length=100) title = models.CharField(max_length=200) description = models.TextField(blank=True) widget_type = models.CharField(max_length=20, choices=WIDGET_TYPES) template_name = models.CharField(max_length=200, help_text="Template to render this widget") data_source = models.CharField(max_length=200, help_text="Function or view that provides data") config = models.JSONField(default=dict, blank=True, help_text="Configuration options for the widget") is_active = models.BooleanField(default=True) order = models.IntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ['order'] def __str__(self): return self.title class UserDashboard(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) widgets = models.ManyToManyField(DashboardWidget, through='UserDashboardWidget') layout_config = models.JSONField(default=dict, blank=True, help_text="Grid layout configuration") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"Dashboard for {self.user.username}" class UserDashboardWidget(models.Model): user_dashboard = models.ForeignKey(UserDashboard, on_delete=models.CASCADE) widget = models.ForeignKey(DashboardWidget, on_delete=models.CASCADE) position = models.JSONField(default=dict, blank=True, help_text="Position in grid layout") config = models.JSONField(default=dict, blank=True, help_text="User-specific configuration") is_visible = models.BooleanField(default=True) class Meta: unique_together = ('user_dashboard', 'widget') ``` ## Dashboard Views ### 2. Dashboard Views Implementation ```python # dashboard/views.py from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.http import HttpResponse from django.template.loader import render_to_string from django.contrib import messages from .models import DashboardWidget, UserDashboard, UserDashboardWidget from inventory.models import Product, Inventory from sales.models import SalesOrder from purchasing.models import PurchaseOrder from manufacturing.models import ManufacturingOrder @login_required def home(request): """Main dashboard view""" # Get or create user dashboard user_dashboard, created = UserDashboard.objects.get_or_create( user=request.user ) # Get visible widgets for this user user_widgets = UserDashboardWidget.objects.filter( user_dashboard=user_dashboard, is_visible=True ).select_related('widget').order_by('widget__order') # Prepare widget data widgets_data = [] for user_widget in user_widgets: widget = user_widget.widget data = get_widget_data(widget.data_source, request) widgets_data.append({ 'widget': widget, 'data': data, 'config': user_widget.config, 'position': user_widget.position, }) context = { 'widgets_data': widgets_data, 'user_dashboard': user_dashboard, } return render(request, 'dashboard/home.html', context) @login_required def print_dashboard(request): """Printable dashboard view""" # Similar to home view but with print-specific template user_dashboard, created = UserDashboard.objects.get_or_create( user=request.user ) user_widgets = UserDashboardWidget.objects.filter( user_dashboard=user_dashboard, is_visible=True ).select_related('widget').order_by('widget__order') widgets_data = [] for user_widget in user_widgets: widget = user_widget.widget data = get_widget_data(widget.data_source, request) widgets_data.append({ 'widget': widget, 'data': data, }) context = { 'widgets_data': widgets_data, 'print_mode': True, } # Render to string for PDF generation if needed html = render_to_string('dashboard/print.html', context, request) return render(request, 'dashboard/print.html', context) def get_widget_data(data_source, request): """Get data for a widget based on its data source""" data_functions = { 'inventory_summary': get_inventory_summary, 'sales_summary': get_sales_summary, 'purchase_summary': get_purchase_summary, 'manufacturing_summary': get_manufacturing_summary, 'low_stock_alerts': get_low_stock_alerts, 'recent_activities': get_recent_activities, } if data_source in data_functions: return data_functions[data_source](request) return {} def get_inventory_summary(request): """Get inventory summary data""" total_products = Product.objects.count() low_stock_items = Inventory.objects.filter( quantity__lte=models.F('product__reorder_level') ).count() return { 'total_products': total_products, 'low_stock_items': low_stock_items, } def get_sales_summary(request): """Get sales summary data""" from django.db.models import Sum from datetime import datetime, timedelta # Get data for last 30 days thirty_days_ago = datetime.now() - timedelta(days=30) total_orders = SalesOrder.objects.filter( order_date__gte=thirty_days_ago ).count() total_value = SalesOrder.objects.filter( order_date__gte=thirty_days_ago ).aggregate( total=Sum('total_amount') )['total'] or 0 return { 'total_orders': total_orders, 'total_value': total_value, } def get_purchase_summary(request): """Get purchase summary data""" from django.db.models import Sum from datetime import datetime, timedelta # Get data for last 30 days thirty_days_ago = datetime.now() - timedelta(days=30) total_orders = PurchaseOrder.objects.filter( order_date__gte=thirty_days_ago ).count() total_value = PurchaseOrder.objects.filter( order_date__gte=thirty_days_ago ).aggregate( total=Sum('total_amount') )['total'] or 0 return { 'total_orders': total_orders, 'total_value': total_value, } def get_manufacturing_summary(request): """Get manufacturing summary data""" total_orders = ManufacturingOrder.objects.count() completed_orders = ManufacturingOrder.objects.filter( status='completed' ).count() return { 'total_orders': total_orders, 'completed_orders': completed_orders, } def get_low_stock_alerts(request): """Get low stock alerts""" from django.db.models import F low_stock_items = Inventory.objects.filter( quantity__lte=F('product__reorder_level') ).select_related('product', 'warehouse')[:10] # Limit to 10 items return { 'items': low_stock_items, } def get_recent_activities(request): """Get recent activities""" # This would integrate with an activity logging system # For now, return empty data return { 'activities': [], } ``` ## Dashboard Templates ### 3. Main Dashboard Template ```html {% extends 'base.html' %} {% block title %}Dashboard - Manufacturing App{% endblock %} {% block content %}

Dashboard

{% for widget_data in widgets_data %}
{% include widget_data.widget.template_name with data=widget_data.data config=widget_data.config %}
{% empty %}

No widgets configured

You don't have any dashboard widgets configured yet.

{% endfor %}
{% endblock %} {% block extra_css %} {% endblock %} {% block extra_js %} {% endblock %} ``` ### 4. Widget Templates #### KPI Widget Template ```html
{{ widget.title }}
{% if data.total_products %}
{{ data.total_products }}
Total Products
{{ data.low_stock_items }}
Low Stock Items
{% else %}
No data available
{% endif %}
``` #### Chart Widget Template ```html
{{ widget.title }}
{% if data.chart_data %} {% else %}
No data available for chart
{% endif %}
{% block extra_js %} {% if data.chart_data %} {% endif %} {% endblock %} ``` #### Table Widget Template ```html
{{ widget.title }}
{% if data.items %}
{% for item in data.items %} {% endfor %}
Product Warehouse Quantity Reorder Level
{{ item.product.name }} {{ item.warehouse.name }} {{ item.quantity }} {{ item.product.reorder_level }}
{% else %}
No data to display
{% endif %}
``` ### 5. Printable Dashboard Template ```html {% extends 'base_print.html' %} {% block title %}Dashboard - Manufacturing App{% endblock %} {% block content %}
{% for widget_data in widgets_data %}

{{ widget_data.widget.title }}

{% if widget_data.widget.widget_type == 'kpi' %} {% include 'dashboard/widgets/kpi_widget_print.html' with data=widget_data.data %} {% elif widget_data.widget.widget_type == 'table' %} {% include 'dashboard/widgets/table_widget_print.html' with data=widget_data.data %} {% else %}
{{ widget_data.data|pprint }}
{% endif %}
{% endfor %}
{% endblock %} {% block extra_css %} {% endblock %} ``` ## Dashboard URLs ### 6. Dashboard URL Configuration ```python # dashboard/urls.py from django.urls import path from . import views app_name = 'dashboard' urlpatterns = [ path('', views.home, name='home'), path('print/', views.print_dashboard, name='print_dashboard'), path('widgets/configure/', views.configure_widgets, name='configure_widgets'), path('widgets//toggle/', views.toggle_widget, name='toggle_widget'), path('widgets//position/', views.update_widget_position, name='update_widget_position'), ] ``` ## Dashboard Configuration Views ### 7. Widget Configuration Views ```python # dashboard/views.py (additional views) @login_required def configure_widgets(request): """Configure dashboard widgets""" user_dashboard, created = UserDashboard.objects.get_or_create( user=request.user ) # Get all available widgets all_widgets = DashboardWidget.objects.filter(is_active=True) # Get user's widgets user_widgets = UserDashboardWidget.objects.filter( user_dashboard=user_dashboard ).select_related('widget') # Create a set of user's widget IDs for easy checking user_widget_ids = set(uw.widget.id for uw in user_widgets) context = { 'all_widgets': all_widgets, 'user_widgets': user_widgets, 'user_widget_ids': user_widget_ids, 'user_dashboard': user_dashboard, } return render(request, 'dashboard/configure.html', context) @login_required def toggle_widget(request, widget_id): """Toggle widget visibility""" if request.method == 'POST': user_dashboard, created = UserDashboard.objects.get_or_create( user=request.user ) widget = get_object_or_404(DashboardWidget, id=widget_id) # Get or create the user widget relationship user_widget, created = UserDashboardWidget.objects.get_or_create( user_dashboard=user_dashboard, widget=widget ) # Toggle visibility user_widget.is_visible = not user_widget.is_visible user_widget.save() messages.success(request, f"Widget {'enabled' if user_widget.is_visible else 'disabled'} successfully") return redirect('dashboard:configure_widgets') return redirect('dashboard:home') @login_required def update_widget_position(request, widget_id): """Update widget position in grid""" if request.method == 'POST': user_dashboard, created = UserDashboard.objects.get_or_create( user=request.user ) widget = get_object_or_404(DashboardWidget, id=widget_id) # Get or create the user widget relationship user_widget, created = UserDashboardWidget.objects.get_or_create( user_dashboard=user_dashboard, widget=widget ) # Update position from POST data position = { 'x': request.POST.get('x', 0), 'y': request.POST.get('y', 0), 'w': request.POST.get('w', 1), 'h': request.POST.get('h', 1), } user_widget.position = position user_widget.save() return JsonResponse({'status': 'success'}) return JsonResponse({'status': 'error'}) ``` ## Dashboard Configuration Template ### 8. Widget Configuration Template ```html {% extends 'base.html' %} {% block title %}Configure Dashboard - Manufacturing App{% endblock %} {% block content %}

Configure Dashboard

Available Widgets
{% for widget in all_widgets %}
{{ widget.title }}

{{ widget.description|truncatewords:15 }}

{% endfor %}
Your Dashboard
Enabled Widgets ({{ user_widgets|length }})
    {% for user_widget in user_widgets %} {% if user_widget.is_visible %}
  • {{ user_widget.widget.title }} {{ user_widget.widget.widget_type }}
  • {% endif %} {% empty %}
  • No widgets enabled
  • {% endfor %}
{% endblock %} {% block extra_js %} {% endblock %} ``` This dashboard implementation plan provides a comprehensive solution for the dashboard requirements, including data visualization, customizable widgets, and printable functionality. The modular design allows for easy extension and customization based on specific business needs.