This commit is contained in:
Marwan Alwali 2025-09-06 16:22:28 +03:00
parent 610e165e17
commit 09932ffe8a
22 changed files with 4061 additions and 399 deletions

View File

@ -1,5 +1,5 @@
from django import forms from django import forms
from django.contrib.auth.models import User from accounts.models import User
from django.utils import timezone from django.utils import timezone
from datetime import timedelta from datetime import timedelta
from patients.models import PatientProfile from patients.models import PatientProfile

View File

@ -8,7 +8,7 @@ urlpatterns = [
path('', views.dashboard, name='dashboard'), path('', views.dashboard, name='dashboard'),
# Donor Management # Donor Management
path('donors/', views.donor_list, name='donor_list'), path('donors/', views.DonorListView.as_view(), name='donor_list'),
path('donors/<int:donor_id>/', views.donor_detail, name='donor_detail'), path('donors/<int:donor_id>/', views.donor_detail, name='donor_detail'),
path('donors/create/', views.donor_create, name='donor_create'), path('donors/create/', views.donor_create, name='donor_create'),
path('donors/<int:donor_id>/update/', views.donor_update, name='donor_update'), path('donors/<int:donor_id>/update/', views.donor_update, name='donor_update'),

View File

@ -1,3 +1,4 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.contrib import messages from django.contrib import messages
@ -10,6 +11,8 @@ from django.contrib.auth.models import User
from datetime import timedelta from datetime import timedelta
import json import json
from django.views.generic import ListView
from .models import ( from .models import (
BloodGroup, Donor, BloodComponent, BloodUnit, BloodTest, CrossMatch, BloodGroup, Donor, BloodComponent, BloodUnit, BloodTest, CrossMatch,
BloodRequest, BloodIssue, Transfusion, AdverseReaction, InventoryLocation, BloodRequest, BloodIssue, Transfusion, AdverseReaction, InventoryLocation,
@ -61,45 +64,50 @@ def dashboard(request):
# Donor Management Views # Donor Management Views
@login_required class DonorListView(LoginRequiredMixin, ListView):
def donor_list(request): model = Donor
"""List all donors with filtering and search""" template_name = 'blood_bank/donors/donor_list.html'
donors = Donor.objects.select_related('blood_group').order_by('-registration_date') context_object_name = 'page_obj'
paginate_by = 25
# Search functionality def get_queryset(self):
search_query = request.GET.get('search') queryset = Donor.objects.select_related('blood_group').order_by('-registration_date')
if search_query:
donors = donors.filter(
Q(donor_id__icontains=search_query) |
Q(first_name__icontains=search_query) |
Q(last_name__icontains=search_query) |
Q(phone__icontains=search_query)
)
# Filter by status # Search functionality
status_filter = request.GET.get('status') search_query = self.request.GET.get('search')
if status_filter: if search_query:
donors = donors.filter(status=status_filter) queryset = queryset.filter(
Q(donor_id__icontains=search_query) |
Q(first_name__icontains=search_query) |
Q(last_name__icontains=search_query) |
Q(phone__icontains=search_query)
)
# Filter by blood group # Filter by status
blood_group_filter = request.GET.get('blood_group') status_filter = self.request.GET.get('status')
if blood_group_filter: if status_filter:
donors = donors.filter(blood_group_id=blood_group_filter) queryset = queryset.filter(status=status_filter)
paginator = Paginator(donors, 25) # Filter by blood group
page_number = request.GET.get('page') blood_group_filter = self.request.GET.get('blood_group')
page_obj = paginator.get_page(page_number) if blood_group_filter:
queryset = queryset.filter(blood_group_id=blood_group_filter)
context = { return queryset
'page_obj': page_obj,
'blood_groups': BloodGroup.objects.all(), def get_context_data(self, **kwargs):
'status_choices': Donor.STATUS_CHOICES, context = super().get_context_data(**kwargs)
'search_query': search_query,
'status_filter': status_filter, context.update({
'blood_group_filter': blood_group_filter, 'blood_groups': BloodGroup.objects.all(),
} 'status_choices': Donor.STATUS_CHOICES,
'search_query': self.request.GET.get('search'),
'status_filter': self.request.GET.get('status'),
'blood_group_filter': self.request.GET.get('blood_group'),
})
return context
return render(request, 'blood_bank/donors/donor_list.html', context)
@login_required @login_required
@ -553,7 +561,7 @@ def inventory_overview(request):
'locations': locations, 'locations': locations,
} }
return render(request, 'blood_bank/inventory/inventory_overview.html', context) return render(request, 'blood_bank/inventory/inventory_dashboard.html', context)
# Quality Control Views # Quality Control Views

View File

@ -28,10 +28,6 @@ from .forms import (
) )
# ============================================================================
# DASHBOARD AND OVERVIEW VIEWS
# ============================================================================
class InventoryDashboardView(LoginRequiredMixin, TemplateView): class InventoryDashboardView(LoginRequiredMixin, TemplateView):
""" """
Main inventory dashboard with comprehensive statistics and recent activity. Main inventory dashboard with comprehensive statistics and recent activity.
@ -52,11 +48,11 @@ class InventoryDashboardView(LoginRequiredMixin, TemplateView):
).count() ).count()
# Stock statistics # Stock statistics
# low_stock_items = InventoryStock.objects.filter( low_stock_items = InventoryStock.objects.filter(
# tenant=user.tenant, inventory_item__tenant=user.tenant,
# quantity_available__lte=F('min_stock_level') quantity_available__lte=F('inventory_item__min_stock_level')
# ).count() ).count()
# context['low_stock_items'] = low_stock_items context['low_stock_items'] = low_stock_items
expired_items = InventoryStock.objects.filter( expired_items = InventoryStock.objects.filter(
inventory_item__tenant=user.tenant, inventory_item__tenant=user.tenant,
@ -84,22 +80,18 @@ class InventoryDashboardView(LoginRequiredMixin, TemplateView):
tenant=user.tenant tenant=user.tenant
).order_by('-created_at')[:10] ).order_by('-created_at')[:10]
# context['low_stock_alerts'] = InventoryStock.objects.filter( context['low_stock_alerts'] = InventoryStock.objects.filter(
# inventory_item__tenant=user.tenant, inventory_item__tenant=user.tenant,
# quantity__lte=F('minimum_stock_level') quantity_available__lte=F('inventory_item__min_stock_level')
# ).select_related('item', 'location').order_by('quantity')[:10] ).select_related('inventory_item', 'location').order_by('quantity_available')[:10]
# context['recent_stock_movements'] = InventoryStock.objects.filter( context['recent_stock_movements'] = InventoryStock.objects.filter(
# tenant=user.tenant inventory_item__tenant=user.tenant
# ).order_by('-updated_at')[:10] ).order_by('-updated_at')[:10]
return context return context
# ============================================================================
# SUPPLIER VIEWS (FULL CRUD - Master Data)
# ============================================================================
class SupplierListView(LoginRequiredMixin, ListView): class SupplierListView(LoginRequiredMixin, ListView):
""" """
List all suppliers with search and filtering capabilities. List all suppliers with search and filtering capabilities.
@ -286,10 +278,6 @@ class SupplierDeleteView(LoginRequiredMixin, DeleteView):
return redirect(self.success_url) return redirect(self.success_url)
# ============================================================================
# INVENTORY LOCATION VIEWS (FULL CRUD - Master Data)
# ============================================================================
class InventoryLocationListView(LoginRequiredMixin, ListView): class InventoryLocationListView(LoginRequiredMixin, ListView):
""" """
List all inventory locations. List all inventory locations.
@ -442,10 +430,6 @@ class InventoryLocationDeleteView(LoginRequiredMixin, DeleteView):
return response return response
# ============================================================================
# INVENTORY ITEM VIEWS (FULL CRUD - Master Data)
# ============================================================================
class InventoryItemListView(LoginRequiredMixin, ListView): class InventoryItemListView(LoginRequiredMixin, ListView):
""" """
List all inventory items with search and filtering. List all inventory items with search and filtering.
@ -609,10 +593,6 @@ class InventoryItemDeleteView(LoginRequiredMixin, DeleteView):
return redirect(self.success_url) return redirect(self.success_url)
# ============================================================================
# INVENTORY STOCK VIEWS (LIMITED CRUD - Operational Data)
# ============================================================================
class InventoryStockListView(LoginRequiredMixin, ListView): class InventoryStockListView(LoginRequiredMixin, ListView):
""" """
List all inventory stock with filtering and search. List all inventory stock with filtering and search.
@ -736,10 +716,6 @@ class InventoryStockUpdateView(LoginRequiredMixin, UpdateView):
return response return response
# ============================================================================
# PURCHASE ORDER VIEWS (RESTRICTED CRUD - Operational Data)
# ============================================================================
class PurchaseOrderListView(LoginRequiredMixin, ListView): class PurchaseOrderListView(LoginRequiredMixin, ListView):
""" """
List all purchase orders with filtering. List all purchase orders with filtering.
@ -872,10 +848,6 @@ class PurchaseOrderUpdateView(LoginRequiredMixin, UpdateView):
return response return response
# ============================================================================
# HTMX AND AJAX VIEWS
# ============================================================================
@login_required @login_required
def inventory_stats(request): def inventory_stats(request):
""" """
@ -898,6 +870,10 @@ def inventory_stats(request):
tenant=user.tenant, tenant=user.tenant,
status__in=['PENDING', 'APPROVED', 'ORDERED'] status__in=['PENDING', 'APPROVED', 'ORDERED']
).count(), ).count(),
'recent_stock_movements': InventoryStock.objects.filter(
inventory_item__tenant=user.tenant,
movement_date__gte=timezone.now().date() - timedelta(days=30)
)
} }
return render(request, 'inventory/partials/inventory_stats.html', stats) return render(request, 'inventory/partials/inventory_stats.html', stats)
@ -919,10 +895,6 @@ def stock_search(request):
}) })
# ============================================================================
# ACTION VIEWS FOR WORKFLOW OPERATIONS
# ============================================================================
@login_required @login_required
def adjust_stock(request, stock_id): def adjust_stock(request, stock_id):
""" """

File diff suppressed because it is too large Load Diff

BIN
templates/.DS_Store vendored

Binary file not shown.

View File

@ -108,39 +108,7 @@
<!-- Pagination --> <!-- Pagination -->
{% if is_paginated %} {% if is_paginated %}
<nav aria-label="Appointment pagination"> {% include 'partial/pagination.html' %}
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">Previous</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">Last</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -94,14 +94,12 @@
<div class="btn-group btn-group-sm" role="group"> <div class="btn-group btn-group-sm" role="group">
<!-- Check In Button --> <!-- Check In Button -->
{% if appointment.status == 'SCHEDULED' or appointment.status == 'CONFIRMED' %} {% if appointment.status == 'SCHEDULED' or appointment.status == 'CONFIRMED' %}
<button type="button" <a type="button"
class="btn btn-outline-success" class="btn btn-outline-success"
title="Check In Patient" title="Check In Patient"
hx-post="{% url 'appointments:check_in_patient' appointment.id %}" href="{% url 'appointments:check_in_patient' appointment.id %}">
hx-target="#appointment-list"
hx-swap="outerHTML">
<i class="fas fa-check"></i> <i class="fas fa-check"></i>
</button> </a>
{% endif %} {% endif %}
<!-- Telemedicine Join Button --> <!-- Telemedicine Join Button -->

View File

@ -27,11 +27,12 @@
</head> </head>
<body> <body>
<!-- Your page content --> <!-- Your page content -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js"></script>
</body> </body>
<script src="{% static 'plugins/apexcharts/dist/apexcharts.min.js' %}"></script> {# <script src="{% static 'plugins/apexcharts/dist/apexcharts.min.js' %}"></script>#}
<script src="{% static 'plugins/chart.js/dist/chart.js' %}"></script>
<!-- HTMX --> <!-- HTMX -->
<script src="{% static 'js/htmx.min.js' %}"></script> <script src="{% static 'js/htmx.min.js' %}"></script>
<!-- ================== END core-css ================== --> <!-- ================== END core-css ================== -->

Binary file not shown.

View File

@ -3,9 +3,9 @@
{% block title %}Blood Bank Dashboard{% endblock %} {% block title %}Blood Bank Dashboard{% endblock %}
{% block extra_css %} {% block css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -346,11 +346,11 @@
<!-- END row --> <!-- END row -->
{% endblock %} {% endblock %}
{% block extra_js %} {% block js %}
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script> <script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {

View File

@ -3,9 +3,9 @@
{% block title %}Donor Management{% endblock %} {% block title %}Donor Management{% endblock %}
{% block extra_css %} {% block css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -182,68 +182,24 @@
<!-- END table --> <!-- END table -->
<!-- BEGIN pagination --> <!-- BEGIN pagination -->
{% if page_obj.has_other_pages %} {% if is_paginated %}
<nav aria-label="Donor pagination"> {% include 'partial/pagination.html' %}
<ul class="pagination justify-content-center"> {% endif %}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
<i class="fa fa-angle-double-left"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
<i class="fa fa-angle-left"></i>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
<i class="fa fa-angle-right"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
<i class="fa fa-angle-double-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
<!-- END pagination --> <!-- END pagination -->
<!-- BEGIN summary --> <!-- BEGIN summary -->
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-6">
<p class="text-muted"> {# <div class="col-md-6 text-end">#}
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} donors {# <div class="btn-group" role="group">#}
</p> {# <button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()">#}
</div> {# <i class="fa fa-print"></i> Print#}
<div class="col-md-6 text-end"> {# </button>#}
<div class="btn-group" role="group"> {# <button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportToCSV()">#}
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()"> {# <i class="fa fa-download"></i> Export#}
<i class="fa fa-print"></i> Print {# </button>#}
</button> {# </div>#}
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportToCSV()"> {# </div>#}
<i class="fa fa-download"></i> Export
</button>
</div>
</div>
</div> </div>
<!-- END summary --> <!-- END summary -->
</div> </div>
@ -251,18 +207,18 @@
<!-- END panel --> <!-- END panel -->
{% endblock %} {% endblock %}
{% block extra_js %} {% block js %}
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script> <script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Initialize DataTable for enhanced functionality // Initialize DataTable for enhanced functionality
$('#donorTable').DataTable({ $('#donorTable').DataTable({
responsive: true, responsive: true,
pageLength: 25, {#pageLength: 25,#}
order: [[0, 'desc']], order: [[0, 'desc']],
columnDefs: [ columnDefs: [
{ orderable: false, targets: [9] } // Actions column { orderable: false, targets: [9] } // Actions column

View File

@ -3,8 +3,8 @@
{% block title %}Blood Bank Inventory Dashboard{% endblock %} {% block title %}Blood Bank Inventory Dashboard{% endblock %}
{% block extra_css %} {% block css %}
<link href="{% static 'assets/plugins/chart.js/dist/Chart.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/chart.js/dist/Chart.min.css' %}" rel="stylesheet" />
<style> <style>
.inventory-card { .inventory-card {
border-radius: 10px; border-radius: 10px;
@ -368,7 +368,7 @@
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
<script src="{% static 'assets/plugins/chart.js/dist/Chart.min.js' %}"></script> <script src="{% static 'plugins/chart.js/dist/chart.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {

View File

@ -4,9 +4,9 @@
{% block title %}Blood Unit Management{% endblock %} {% block title %}Blood Unit Management{% endblock %}
{% block extra_css %} {% block extra_css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -250,62 +250,20 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<!-- END table --> <!-- END table -->
<!-- BEGIN pagination --> <!-- BEGIN pagination -->
{% if page_obj.has_other_pages %} {% if is_paginated %}
<nav aria-label="Blood unit pagination"> {% include 'partial/pagination.html' %}
<ul class="pagination justify-content-center"> {% endif %}
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1">
<i class="fa fa-angle-double-left"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">
<i class="fa fa-angle-left"></i>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">
<i class="fa fa-angle-right"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">
<i class="fa fa-angle-double-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
<!-- END pagination --> <!-- END pagination -->
<!-- BEGIN summary --> <!-- BEGIN summary -->
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-6">
<p class="text-muted">
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} blood units
</p>
</div>
<div class="col-md-6 text-end"> <div class="col-md-6 text-end">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()"> <button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()">

View File

@ -335,7 +335,7 @@
{% block js %} {% block js %}
<!-- DataTables JS --> <!-- DataTables JS -->
<script src="{% static 'plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script> <script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>

View File

@ -45,141 +45,58 @@
</div> </div>
<!-- Key Performance Indicators --> <!-- Key Performance Indicators -->
<div class="row mb-4" hx-get="{% url 'inventory:inventory_stats' %}" hx-trigger="load, every 30s"> <div class="row mb-4" hx-get="{% url 'inventory:inventory_stats' %}">
<div class="col-lg-3 col-md-6 mb-3"> <div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100"> <div class="card stat-card bg-success text-white">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
<h6 class="card-title text-muted mb-1">Total Items</h6> <h4 class="card-title">{{ total_items }}</h4>
<h3 class="mb-0 text-primary">{{ total_items }}</h3> <p class="card-text">Total Items</p>
<small class="text-muted">{{ active_items }} active</small>
</div>
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-boxes fa-lg text-white"></i>
</div> </div>
<i class="fas fa-boxes fa-2x opacity-75"></i>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6 mb-3"> <div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100"> <div class="card stat-card bg-warning">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
<h6 class="card-title text-muted mb-1">Locations</h6> <h4 class="card-title">{{ total_locations }}</h4>
<h3 class="mb-0 text-success">{{ total_locations }}</h3> <p class="card-text">Locations</p>
<small class="text-muted">Storage areas</small>
</div>
<div class="bg-success bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-map-marker-alt fa-lg text-white"></i>
</div> </div>
<i class="fas fa-map-marker-alt fa-2x opacity-75"></i>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6 mb-3"> <div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100"> <div class="card stat-card bg-primary text-white">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
<h6 class="card-title text-muted mb-1">Suppliers</h6> <h4 class="card-title">{{ total_suppliers }}</h4>
<h3 class="mb-0 text-info">{{ total_suppliers }}</h3> <p class="card-text">Suppliers</p>
<small class="text-muted">Active partners</small>
</div>
<div class="bg-info bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-truck fa-lg text-white"></i>
</div> </div>
<i class="fas fa-truck fa-2x opacity-75"></i>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6 mb-3"> <div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100"> <div class="card stat-card bg-danger text-white">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div> <div>
<h6 class="card-title text-muted mb-1">Total Value</h6> <h4 class="card-title"><span class="symbol">&#xea;</span>{{ total_inventory_value|floatformat:'2g' }}</h4>
<h3 class="mb-0 text-warning">${{ total_inventory_value|floatformat:0 }}</h3> <p class="card-text">Total Value</p>
<small class="text-muted">Inventory worth</small>
</div>
<div class="bg-warning bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-dollar-sign fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Alert Cards -->
<div class="row mb-4">
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100 {% if low_stock_items > 0 %}border-warning{% endif %}">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Low Stock</h6>
<h3 class="mb-0 {% if low_stock_items > 0 %}text-warning{% else %}text-success{% endif %}">{{ low_stock_items }}</h3>
<small class="text-muted">Items below minimum</small>
</div>
<div class="bg-{% if low_stock_items > 0 %}warning{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-exclamation-triangle fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100 {% if expired_items > 0 %}border-danger{% endif %}">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Expired</h6>
<h3 class="mb-0 {% if expired_items > 0 %}text-danger{% else %}text-success{% endif %}">{{ expired_items }}</h3>
<small class="text-muted">Past expiry date</small>
</div>
<div class="bg-{% if expired_items > 0 %}danger{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-calendar-times fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100 {% if expiring_soon_items > 0 %}border-warning{% endif %}">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Expiring Soon</h6>
<h3 class="mb-0 {% if expiring_soon_items > 0 %}text-warning{% else %}text-success{% endif %}">{{ expiring_soon_items }}</h3>
<small class="text-muted">Within 30 days</small>
</div>
<div class="bg-{% if expiring_soon_items > 0 %}warning{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-clock fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Active Orders</h6>
<h3 class="mb-0 text-primary">{{ active_orders }}</h3>
<small class="text-muted">In progress</small>
</div>
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-shopping-cart fa-lg text-white"></i>
</div> </div>
<i class="fas fa-dollar-sign fa-2x opacity-75"></i>
</div> </div>
</div> </div>
</div> </div>
@ -195,9 +112,9 @@
<div class="panel-heading-btn"> <div class="panel-heading-btn">
<a href="{% url 'inventory:purchase_order_list' %}" class="btn btn-outline-primary btn-xs"><i class="fas fa-list me-1"></i>View All</a> <a href="{% url 'inventory:purchase_order_list' %}" class="btn btn-outline-primary btn-xs"><i class="fas fa-list me-1"></i>View All</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a> <a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@ -216,20 +133,20 @@
<tbody> <tbody>
{% for order in recent_orders %} {% for order in recent_orders %}
<tr> <tr>
<td> <td class="fs-12px">
<a href="{% url 'inventory:purchase_order_detail' order.pk %}" <a href="{% url 'inventory:purchase_order_detail' order.pk %}"
class="text-decoration-none fw-semibold"> class="text-decoration-none fw-semibold">
{{ order.order_number }} {{ order.po_number }}
</a> </a>
</td> </td>
<td>{{ order.supplier.name|truncatechars:20 }}</td> <td class="fs-12px">{{ order.supplier.name }}</td>
<td> <td class="fs-12px">
<span class="badge bg-{% if order.status == 'RECEIVED' %}success{% elif order.status == 'APPROVED' %}info{% elif order.status == 'ORDERED' %}warning{% else %}secondary{% endif %}"> <span class="badge bg-{% if order.status == 'RECEIVED' %}success{% elif order.status == 'APPROVED' %}info{% elif order.status == 'ORDERED' %}warning{% else %}secondary{% endif %}">
{{ order.get_status_display }} {{ order.get_status_display }}
</span> </span>
</td> </td>
<td><span class="symbol">&#xea;</span>{{ order.total_amount|floatformat:'2g' }}</td> <td class="fs-12px"><span class="symbol">&#xea;</span>{{ order.total_amount|floatformat:'2g' }}</td>
<td>{{ order.order_date|date:" Y M d" }}</td> <td class="fs-12px">{{ order.order_date|date:" Y M d" }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -257,9 +174,9 @@
<div class="panel-heading-btn"> <div class="panel-heading-btn">
<a href="{% url 'inventory:stock_list' %}?stock_status=low" class="btn btn-outline-warning btn-xs"><i class="fas fa-list me-1"></i>View All</a> <a href="{% url 'inventory:stock_list' %}?stock_status=low" class="btn btn-outline-warning btn-xs"><i class="fas fa-list me-1"></i>View All</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a> <a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@ -308,7 +225,7 @@
<div class="panel-body"> <div class="panel-body">
{% if recent_stock_movements %} {% if recent_stock_movements %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover mb-0"> <table class="table table-sm table-hover mb-0">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>Item</th> <th>Item</th>
@ -320,19 +237,19 @@
<tbody> <tbody>
{% for stock in recent_stock_movements %} {% for stock in recent_stock_movements %}
<tr> <tr>
<td> <td class="fs-12px">
<a href="{% url 'inventory:stock_detail' stock.pk %}" <a href="{% url 'inventory:stock_detail' stock.pk %}"
class="text-decoration-none"> class="text-decoration-none">
{{ stock.item.item_name|truncatechars:25 }} {{ stock.inventory_item.item_name }}
</a> </a>
</td> </td>
<td>{{ stock.location.location_name|truncatechars:15 }}</td> <td class="fs-12px">{{ stock.location.name }}</td>
<td> <td class="fs-12px">
<span class="{% if stock.quantity <= stock.minimum_stock_level %}text-warning{% else %}text-success{% endif %} fw-semibold"> <span class="{% if stock.quantity_available <= stock.inventory_item.min_stock_level %}text-warning{% else %}text-success{% endif %} fw-semibold">
{{ stock.quantity }} {{ stock.quantity_available }}
</span> </span>
</td> </td>
<td>{{ stock.updated_at|date:"M d, H:i" }}</td> <td class="fs-12px">{{ stock.updated_at|date:"M d, H:i" }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -415,9 +332,9 @@
</h4> </h4>
<div class="panel-heading-btn"> <div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a> <a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@ -434,9 +351,9 @@
</h4> </h4>
<div class="panel-heading-btn"> <div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a> <a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a> {# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@ -446,6 +363,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="{% static 'plugins/chart.js/dist/chart.umd.js' %}"></script>
<script> <script>
// Dashboard functionality // Dashboard functionality
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
@ -453,7 +371,7 @@ document.addEventListener('DOMContentLoaded', function() {
initializeCharts(); initializeCharts();
// Auto-refresh dashboard every 5 minutes // Auto-refresh dashboard every 5 minutes
setInterval(refreshDashboard, 300000); {#setInterval(refreshDashboard, 300000);#}
}); });
function refreshDashboard() { function refreshDashboard() {
@ -472,7 +390,7 @@ function refreshDashboard() {
setTimeout(() => { setTimeout(() => {
refreshBtn.innerHTML = originalText; refreshBtn.innerHTML = originalText;
refreshBtn.disabled = false; refreshBtn.disabled = false;
}, 2000); }, 300000);
} }
function initializeCharts() { function initializeCharts() {
@ -486,7 +404,7 @@ function initializeCharts() {
datasets: [{ datasets: [{
data: [16, 12, 14, 10, 18, 20, 4], data: [16, 12, 14, 10, 18, 20, 4],
backgroundColor: [ backgroundColor: [
'#0d6efd', '#198754', '#ffc107', '#dc3545', '#0d6efd', '#198754', '#ffc107', '#dc3545',
'#6f42c1', '#fd7e14', '#20c997', '#6c757d' '#6f42c1', '#fd7e14', '#20c997', '#6c757d'
] ]
}] }]
@ -502,7 +420,7 @@ function initializeCharts() {
} }
}); });
} }
// Stock Status Chart // Stock Status Chart
const stockCtx = document.getElementById('stockStatusChart'); const stockCtx = document.getElementById('stockStatusChart');
if (stockCtx) { if (stockCtx) {

View File

@ -3,10 +3,10 @@
{% block title %}Insurance Claims Management{% endblock %} {% block title %}Insurance Claims Management{% endblock %}
{% block extra_css %} {% block css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
<style> <style>
.stats-card { .stats-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@ -432,12 +432,12 @@
</div> </div>
{% endblock %} {% endblock %}
{% block extra_js %} {% block js %}
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script> <script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script> <script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {

View File

@ -4,9 +4,9 @@
{% block title %}Emergency Contacts - Patient Management{% endblock %} {% block title %}Emergency Contacts - Patient Management{% endblock %}
{% block css %} {% block css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" /> <link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -292,11 +292,11 @@
{% endblock %} {% endblock %}
{% block js %} {% block js %}
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script> <script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script> <script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script> <script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
var table; var table;