devicehub-django/lot/views.py

413 lines
13 KiB
Python
Raw Permalink Normal View History

from django.db import IntegrityError
2024-07-09 11:35:35 +00:00
from django.urls import reverse_lazy
2024-12-18 12:55:00 +00:00
from django.shortcuts import get_object_or_404, redirect, Http404
from django.contrib import messages
2025-02-27 02:45:48 +00:00
from dashboard.mixins import InventaryMixin, DetailsMixin
2024-07-09 11:35:35 +00:00
from django.utils.translation import gettext_lazy as _
2025-02-24 19:13:34 +00:00
from django.utils.safestring import mark_safe
2024-07-10 11:55:57 +00:00
from django.views.generic.base import TemplateView
from django.db.models import Q
2024-07-09 11:35:35 +00:00
from django.views.generic.edit import (
CreateView,
2024-07-10 11:55:57 +00:00
DeleteView,
2024-07-09 11:35:35 +00:00
UpdateView,
2024-07-19 15:40:01 +00:00
FormView,
2024-07-09 11:35:35 +00:00
)
import django_tables2 as tables
2024-07-09 15:31:24 +00:00
from dashboard.mixins import DashboardView
2025-02-27 02:45:48 +00:00
from evidence.models import SystemProperty
from device.models import Device
2024-11-16 15:31:02 +00:00
from lot.models import Lot, LotTag, LotProperty
2024-07-09 15:31:24 +00:00
from lot.forms import LotsForm
2024-07-09 11:35:35 +00:00
class LotSuccessUrlMixin():
2025-02-27 02:45:48 +00:00
success_url = reverse_lazy('lot:unassigned') #default_url
def get_success_url(self):
lot_group_id = LotTag.objects.only('id').get(
owner=self.object.owner,
name=self.object.type
).id
#null checking just in case
if not lot_group_id:
return self.success_url
return reverse_lazy('lot:tags', args=[lot_group_id])
class NewLotView(LotSuccessUrlMixin ,DashboardView, CreateView):
2024-07-09 11:35:35 +00:00
template_name = "new_lot.html"
title = _("New lot")
breadcrumb = "lot / New lot"
model = Lot
fields = (
"type",
"name",
"code",
"description",
"closed",
)
2025-02-17 12:05:41 +00:00
def get_form(self):
form = super().get_form()
form.fields["type"].queryset = LotTag.objects.filter(
owner=self.request.user.institution,
inbox=False
)
return form
2024-07-09 11:35:35 +00:00
def form_valid(self, form):
2025-02-24 14:44:19 +00:00
try:
form.instance.owner = self.request.user.institution
form.instance.user = self.request.user
response = super().form_valid(form)
messages.success(self.request, _("Lot created successfully."))
2025-02-24 14:44:19 +00:00
return response
except IntegrityError:
messages.error(self.request, _("Lot name is already defined."))
return self.form_invalid(form)
2024-07-09 11:35:35 +00:00
return response
class DeleteLotView(LotSuccessUrlMixin, DashboardView, DeleteView):
2024-07-10 11:55:57 +00:00
template_name = "delete_lot.html"
title = _("Delete lot")
breadcrumb = "lot / Delete lot"
model = Lot
fields = (
"type",
"name",
"code",
"description",
"closed",
)
def form_valid(self, form):
response = super().form_valid(form)
messages.warning(self.request, _("Lot '{}' was successfully deleted.").format(self.object.name))
return response
def form_invalid(self, form):
response = super().form_invalid(form)
messages.error(self.request, _("Error deleting the lot."))
2024-07-10 11:55:57 +00:00
return response
class EditLotView(LotSuccessUrlMixin, DashboardView, UpdateView):
2024-07-09 11:35:35 +00:00
template_name = "new_lot.html"
2024-07-10 11:55:57 +00:00
title = _("Edit lot")
breadcrumb = "Lot / Edit lot"
2024-07-09 11:35:35 +00:00
model = Lot
fields = (
"type",
"name",
"code",
"description",
"closed",
)
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
2024-10-09 16:00:56 +00:00
self.object = get_object_or_404(
self.model,
owner=self.request.user.institution,
pk=pk,
)
2024-07-09 11:35:35 +00:00
# self.success_url = reverse_lazy('dashbiard:lot', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs
2024-07-09 15:31:24 +00:00
2025-02-20 17:10:37 +00:00
def get_form(self):
form = super().get_form()
form.fields["type"].queryset = LotTag.objects.filter(
owner=self.request.user.institution,
inbox=False
)
return form
def form_valid(self, form):
response = super().form_valid(form)
messages.warning(self.request, _("Lot '{}' was successfully edited.").format(self.object.name))
return response
def form_invalid(self, form):
response = super().form_invalid(form)
messages.error(self.request, _("Error editing the lot."))
return response
2024-07-10 11:55:57 +00:00
2024-07-09 15:31:24 +00:00
class AddToLotView(DashboardView, FormView):
template_name = "list_lots.html"
title = _("Add to lots")
breadcrumb = "lot / add to lots"
2025-02-27 02:45:48 +00:00
success_url = reverse_lazy('lot:unassigned')
2024-07-09 15:31:24 +00:00
form_class = LotsForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
2024-10-09 16:00:56 +00:00
lots = Lot.objects.filter(owner=self.request.user.institution)
lot_tags = LotTag.objects.filter(owner=self.request.user.institution)
2024-07-09 15:31:24 +00:00
context.update({
'lots': lots,
2024-07-18 15:21:22 +00:00
'lot_tags':lot_tags,
2024-07-09 15:31:24 +00:00
})
return context
def get_form(self):
form = super().get_form()
form.fields["lots"].queryset = Lot.objects.filter(
owner=self.request.user.institution)
2024-07-09 15:31:24 +00:00
return form
def form_valid(self, form):
form.devices = self.get_session_devices()
form.save()
response = super().form_valid(form)
return response
2024-07-10 08:24:40 +00:00
class DelToLotView(AddToLotView):
title = _("Remove from lots")
breadcrumb = "lot / remove from lots"
def form_valid(self, form):
form.devices = self.get_session_devices()
form.remove()
response = super().form_valid(form)
return response
class LotTable(tables.Table):
2025-02-27 02:45:48 +00:00
name = tables.Column(linkify=("lot:lot", {"pk": tables.A("id")}), verbose_name=_("Lot Name"), attrs={"td": {"class": "fw-bold"}})
2025-02-24 19:13:34 +00:00
description = tables.Column(verbose_name=_("Description"), default=_("No description"),attrs={"td": {"class": "text-muted"}} )
closed = tables.Column(verbose_name=_("Status"))
created = tables.DateColumn(format="Y-m-d", verbose_name=_("Created On"))
2025-02-24 19:13:34 +00:00
user = tables.Column(verbose_name=("Created By"), default=_("Unknown"), attrs={"td": {"class": "text-muted"}} )
actions = tables.TemplateColumn(
template_name="lot_actions.html",
2025-02-24 19:13:34 +00:00
verbose_name=_(""),
attrs={"td": {"class": "text-end"}}
)
2025-02-24 19:13:34 +00:00
def render_closed(self, value):
if value:
return mark_safe('<span class="badge bg-danger">Closed</span>')
return mark_safe('<span class="badge bg-success">Open</span>')
class Meta:
model = Lot
2025-02-24 19:13:34 +00:00
fields = ("closed", "name", "description", "created", "user", "actions")
attrs = {
"class": "table table-hover align-middle",
"thead": {"class": "table-light"}
}
2025-02-24 19:13:34 +00:00
order_by = ("-created",)
class LotsTagsView(DashboardView, tables.SingleTableView):
2024-07-10 11:55:57 +00:00
template_name = "lots.html"
2025-02-27 02:45:48 +00:00
title = _("Lot group")
2024-07-18 15:21:22 +00:00
breadcrumb = _("lots") + " /"
2025-02-27 02:45:48 +00:00
success_url = reverse_lazy('lot:unassigned')
model = Lot
table_class = LotTable
def get_queryset(self):
self.pk = self.kwargs.get('pk')
self.tag = get_object_or_404(LotTag, owner=self.request.user.institution, id=self.pk)
2025-02-21 23:45:39 +00:00
self.show_open = self.request.GET.get('show_open', 'false') == 'true'
self.show_closed = self.request.GET.get('show_closed', 'false')
self.search_query = self.request.GET.get('q', '').strip()
queryset = Lot.objects.filter(owner=self.request.user.institution, type=self.tag)
2025-02-21 23:45:39 +00:00
if self.show_closed == 'true':
queryset = queryset.filter(closed=True)
2025-02-21 23:45:39 +00:00
elif self.show_closed == 'false':
queryset = queryset.filter(closed=False)
if self.search_query:
queryset = queryset.filter(
Q(name__icontains=self.search_query) |
Q(description__icontains=self.search_query) |
Q(code__icontains=self.search_query)
)
sort = self.request.GET.get('sort')
if sort:
queryset = queryset.order_by(sort)
return queryset
2024-07-10 11:55:57 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'title': self.title + " " + self.tag.name,
'breadcrumb': self.breadcrumb + " " + self.tag.name,
'show_closed': self.show_closed,
2025-02-21 23:45:39 +00:00
'search_query': self.search_query,
2024-07-10 11:55:57 +00:00
})
return context
2024-11-16 15:31:02 +00:00
class LotPropertiesView(DashboardView, TemplateView):
template_name = "properties.html"
title = _("New Lot Property")
breadcrumb = "Lot / New property"
2024-07-30 11:37:08 +00:00
def get_context_data(self, **kwargs):
self.pk = kwargs.get('pk')
context = super().get_context_data(**kwargs)
2024-10-09 16:00:56 +00:00
lot = get_object_or_404(Lot, owner=self.request.user.institution, id=self.pk)
2024-11-16 15:31:02 +00:00
properties = LotProperty.objects.filter(
2024-07-30 11:37:08 +00:00
lot=lot,
2024-10-09 16:00:56 +00:00
owner=self.request.user.institution,
2024-12-10 19:53:07 +00:00
type=LotProperty.Type.USER,
2024-07-30 11:37:08 +00:00
)
context.update({
'lot': lot,
2024-11-16 15:31:02 +00:00
'properties': properties,
2024-07-30 11:37:08 +00:00
'title': self.title,
'breadcrumb': self.breadcrumb
})
return context
2024-12-18 12:55:00 +00:00
class AddLotPropertyView(DashboardView, CreateView):
2024-11-16 15:31:02 +00:00
template_name = "new_property.html"
title = _("New Lot Property")
breadcrumb = "Device / New property"
2025-02-27 02:45:48 +00:00
success_url = reverse_lazy('lot:unassigned_devices')
2024-11-16 15:31:02 +00:00
model = LotProperty
2024-07-30 11:37:08 +00:00
fields = ("key", "value")
def form_valid(self, form):
2024-10-09 16:00:56 +00:00
form.instance.owner = self.request.user.institution
form.instance.user = self.request.user
2024-07-30 11:37:08 +00:00
form.instance.lot = self.lot
2024-12-10 19:53:07 +00:00
form.instance.type = LotProperty.Type.USER
try:
response = super().form_valid(form)
messages.success(self.request, _("Property successfully added."))
return response
except IntegrityError:
messages.error(self.request, _("Property is already defined."))
return self.form_invalid(form)
2024-07-30 11:37:08 +00:00
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
2024-10-09 16:00:56 +00:00
self.lot = get_object_or_404(Lot, pk=pk, owner=self.request.user.institution)
2024-11-16 15:31:02 +00:00
self.success_url = reverse_lazy('lot:properties', args=[pk])
2024-07-30 11:37:08 +00:00
kwargs = super().get_form_kwargs()
return kwargs
2024-12-18 12:55:00 +00:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['lot_id'] = self.lot.id
return context
2024-12-18 12:55:00 +00:00
class UpdateLotPropertyView(DashboardView, UpdateView):
template_name = "properties.html"
title = _("Update lot Property")
breadcrumb = "Lot / Update Property"
model = LotProperty
fields = ("key", "value")
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
lot_property = get_object_or_404(
LotProperty,
pk=pk,
owner=self.request.user.institution
)
2024-12-18 12:55:00 +00:00
if not lot_property:
raise Http404
lot_pk = lot_property.lot.pk
self.success_url = reverse_lazy('lot:properties', args=[lot_pk])
2024-12-18 12:55:00 +00:00
kwargs = super().get_form_kwargs()
kwargs['instance'] = lot_property
return kwargs
def form_valid(self, form):
try:
response = super().form_valid(form)
messages.success(self.request, _("Property updated successfully."))
return response
except IntegrityError:
messages.error(self.request, _("Property is already defined."))
return self.form_invalid(form)
2024-12-18 12:55:00 +00:00
def form_invalid(self, form):
super().form_invalid(form)
return redirect(self.get_success_url())
2024-12-18 12:55:00 +00:00
class DeleteLotPropertyView(DashboardView, DeleteView):
model = LotProperty
def post(self, request, *args, **kwargs):
self.pk = kwargs['pk']
self.object = get_object_or_404(
self.model,
pk=self.pk,
owner=self.request.user.institution
)
lot_pk = self.object.lot.pk
2024-12-18 12:55:00 +00:00
self.object.delete()
messages.success(self.request, _("Lot property deleted successfully."))
self.success_url = reverse_lazy('lot:properties', args=[lot_pk])
2024-12-18 12:55:00 +00:00
# Redirect back to the original URL
return redirect(self.success_url)
2025-02-27 02:45:48 +00:00
class UnassignedDevicesView(InventaryMixin):
template_name = "unassigned_devices.html"
section = "Unassigned"
title = _("Unassigned Devices")
breadcrumb = "Devices / Unassigned Devices"
def get_devices(self, user, offset, limit):
return Device.get_unassigned(self.request.user.institution, offset, limit)
class LotView(InventaryMixin, DetailsMixin):
template_name = "unassigned_devices.html"
section = "dashboard_lot"
breadcrumb = "Lot / Devices"
model = Lot
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
lot = context.get('object')
context.update({
'lot': lot,
'title': _("Lot {}".format(lot.name))
})
return context
def get_devices(self, user, offset, limit):
chids = self.object.devicelot_set.all().values_list(
"device_id", flat=True
).distinct()
props = SystemProperty.objects.filter(
owner=self.request.user.institution,
value__in=chids
).order_by("-created")
chids_ordered = []
for x in props:
if x.value not in chids_ordered:
chids_ordered.append(x.value)
chids_page = chids_ordered[offset:offset+limit]
return [Device(id=x) for x in chids_page], len(chids_ordered)