update
This commit is contained in:
parent
610e165e17
commit
09932ffe8a
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||||
|
|||||||
@ -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'),
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Binary file not shown.
@ -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
BIN
templates/.DS_Store
vendored
Binary file not shown.
@ -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 %}
|
||||||
|
|
||||||
|
|||||||
@ -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 -->
|
||||||
|
|||||||
@ -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 ================== -->
|
||||||
|
|||||||
BIN
templates/blood_bank/.DS_Store
vendored
BIN
templates/blood_bank/.DS_Store
vendored
Binary file not shown.
@ -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() {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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()">
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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">ê</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">ê</span>{{ order.total_amount|floatformat:'2g' }}</td>
|
<td class="fs-12px"><span class="symbol">ê</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) {
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user