-
- Weight:
-
-
- {{ object.physicalproperties.weight }}
-
+
+
-
-
width:
-
- {{ object.physicalproperties.width }}
-
-
-
-
-
height:
-
- {{ object.physicalproperties.height }}
-
-
-
-
-
depth:
-
- {{ object.physicalproperties.depth }}
-
-
-
-
-
color:
-
- {{ object.physicalproperties.color }}
-
-
-
-
-
image:
-
- {% if object.physicalproperties.image %}
-
- {% endif %}
-
-
- {% endif %}
+
Annotations
+
+
+
+ Key |
+ Value |
+ Created on |
+ |
+ |
+
+
+
+ {% for a in object.annotations %}
+ {% if a.is_user_annotation %}
+
+ {{ a.key }} |
+ {{ a.value }} |
+ {{ a.created }} |
+ |
+ |
+
+ {% endif %}
+ {% endfor %}
+
+
+
-
Incoming Lots
+ {% for tag in lot_tags %}
+
{{ tag }}
+ {% for lot in object.lot_set.filter %}
+ {% if lot.type == tag %}
-
-
-
-
Outgoing Lots
-
-
-
-
-
-
Temporary Lots
-
-
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
@@ -188,28 +171,6 @@
-
-
Status Details
-
-
-
Lifecycle State
-
-
-
-
-
-
Allocated State
-
-
-
-
-
-
Traceability log Details
@@ -233,35 +194,42 @@
-
Components Snapshot
+
Components last snapshot
-
+ {% for c in snapshot.components %}
-
Motherboard
- 14:07 23-06-2024
+ {{ c.type }}
+ {{ snapshot.created }}
- hp
- 890e
+ {{ c.manufacturer }}
+ {{ c.model }}
+ {{ c.serialNumber }}
-
+ {% endfor %}
+
+
+
+
+
List of snapshots
+
+ {% for snap in object.snapshots %}
-
NetworkAdapter
- 14:07 23-06-2024
+
+ {{ snap.created }}
- realtek semiconductor co., ltd.
- rtl8852ae 802.11ax pcie wireless network adapter
+ {{ snap.uuid }}
-
+ {% endfor %}
diff --git a/device/urls.py b/device/urls.py
index 33260e9..7fc0e96 100644
--- a/device/urls.py
+++ b/device/urls.py
@@ -5,7 +5,7 @@ app_name = 'device'
urlpatterns = [
path("add/", views.NewDeviceView.as_view(), name="add"),
- path("edit/
/", views.EditDeviceView.as_view(), name="edit"),
- path("/", views.DetailsView.as_view(), name="details"),
- path("physical//", views.PhysicalView.as_view(), name="physical_edit"),
+ path("edit//", views.EditDeviceView.as_view(), name="edit"),
+ path("/", views.DetailsView.as_view(), name="details"),
+ path("/annotation/add", views.AddAnnotationView.as_view(), name="add_annotation"),
]
diff --git a/device/views.py b/device/views.py
index 0285529..00255dd 100644
--- a/device/views.py
+++ b/device/views.py
@@ -11,7 +11,8 @@ from django.views.generic.base import TemplateView
from dashboard.mixins import DashboardView, DetailsMixin
from snapshot.models import Annotation
from snapshot.xapian import search
-from device.models import Device, PhysicalProperties
+from lot.models import LotTag
+from device.models import Device
class NewDeviceView(DashboardView, CreateView):
@@ -20,26 +21,12 @@ class NewDeviceView(DashboardView, CreateView):
breadcrumb = "Device / New Device"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = Device
- fields = (
- 'type',
- "model",
- "manufacturer",
- "serial_number",
- "part_number",
- "brand",
- "generation",
- "version",
- "production_date",
- "variant",
- "family",
- )
def form_valid(self, form):
form.instance.owner = self.request.user
response = super().form_valid(form)
- PhysicalProperties.objects.create(device=form.instance)
return response
-
+
class EditDeviceView(DashboardView, UpdateView):
template_name = "new_device.html"
@@ -47,19 +34,6 @@ class EditDeviceView(DashboardView, UpdateView):
breadcrumb = "Device / Update Device"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = Device
- fields = (
- 'type',
- "model",
- "manufacturer",
- "serial_number",
- "part_number",
- "brand",
- "generation",
- "version",
- "production_date",
- "variant",
- "family",
- )
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
@@ -67,73 +41,53 @@ class EditDeviceView(DashboardView, UpdateView):
self.success_url = reverse_lazy('device:details', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs
-
-class DetailsView2(DetailsMixin):
+
+class DetailsView(DetailsMixin):
template_name = "details.html"
title = _("Device")
breadcrumb = "Device / Details"
model = Device
-class DetailsView(DashboardView, TemplateView):
- template_name = "details.html"
- title = _("Device")
- breadcrumb = "Device / Details"
-
- def get(self, request, *args, **kwargs):
- # import pdb; pdb.set_trace()
- self.pk = kwargs['pk']
- annotation = get_object_or_404(Annotation, owner=self.request.user, uuid=self.pk)
- for xa in search([str(self.pk)]):
- self.object = json.loads(xa.document.get_data())
- return super().get(request, *args, **kwargs)
-
- return super().get(request, *args, **kwargs)
-
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
+ self.object.initial()
+ lot_tags = LotTag.objects.filter(owner=self.request.user)
context.update({
- 'object': self.object,
+ 'snapshot': self.object.get_last_snapshot(),
+ 'lot_tags': lot_tags,
})
return context
-
-class PhysicalView(DashboardView, UpdateView):
- template_name = "physical_properties.html"
- title = _("Physical Properties")
- breadcrumb = "Device / Physical properties"
+class AddAnnotationView(DashboardView, CreateView):
+ template_name = "new_device.html"
+ title = _("New annotation")
+ breadcrumb = "Device / New annotation"
success_url = reverse_lazy('dashboard:unassigned_devices')
- model = PhysicalProperties
- fields = (
- "weight",
- "width",
- "height",
- "depth",
- "color",
- "image",
- )
+ model = Annotation
+ fields = ("key", "value")
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- context.update({
- 'device': self.device,
- })
- return context
+ def form_valid(self, form):
+ self.device.get_annotations()
+ self.device.get_uuids()
+ form.instance.owner = self.request.user
+ form.instance.device = self.device
+ form.instance.uuid = self.device.uuids[0]
+ form.instance.type = Annotation.Type.USER
+ response = super().form_valid(form)
+ return response
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
self.device = get_object_or_404(Device, pk=pk)
- try:
- self.object = self.device.physicalproperties
- except Exception:
- self.object = PhysicalProperties.objects.create(device=self.device)
+ self.success_url = reverse_lazy('device:details', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs
-
- def form_valid(self, form):
- self.success_url = reverse_lazy('device:details', args=[self.device.id])
- response = super().form_valid(form)
- return response
-
+
+ def get_success_url(self):
+ url = super().get_success_url()
+ import pdb; pdb.set_trace()
+ return url
+
diff --git a/example/snapshot1.json b/example/snapshot1.json
new file mode 100644
index 0000000..bc49da5
--- /dev/null
+++ b/example/snapshot1.json
@@ -0,0 +1 @@
+{"type": "Snapshot", "components": [{"type": "SoundCard", "model": "Xeon E3-1200 V3/4th Gen Core Processor Hd Audio Controller", "manufacturer": "Intel Corporation"}, {"type": "SoundCard", "model": "Hp Hd Webcam", "manufacturer": "Chicony Electronics Co.,ltd.", "serialNumber": "200901010001"}, {"type": "SoundCard", "model": "8 Series/c220 Series Chipset High Definition Audio Controller", "manufacturer": "Intel Corporation"}, {"type": "RamModule", "model": "M471b5273ch0-Yk0", "manufacturer": "Samsung", "serialNumber": "96C0FA89", "size": 4096, "speed": 1600, "interface": "DDR3", "format": "SODIMM"}, {"type": "Processor", "actions": [{"type": "BenchmarkProcessor", "elapsed": 0, "rate": 19951.48}, {"type": "BenchmarkProcessorSysbench", "elapsed": 15, "rate": 14.6652}], "model": "Intel Core I5-4200m Cpu @ 2.50ghz", "manufacturer": "Intel Corp.", "brand": "Core i5", "generation": 4, "speed": 2.524414, "cores": 2, "threads": 4, "address": 64}, {"type": "NetworkAdapter", "model": "Ethernet Connection I217-V", "manufacturer": "Intel Corporation", "serialNumber": "FC:15:B4:E7:5D:D7", "variant": "04", "speed": 1000, "wireless": false}, {"type": "NetworkAdapter", "model": "Bcm43228 802.11a/b/g/n", "manufacturer": "Broadcom Inc. and Subsidiaries", "variant": "00", "wireless": false}, {"type": "SolidStateDrive", "actions": [{"type": "BenchmarkDataStorage", "elapsed": 2, "readSpeed": 487, "writeSpeed": 179}], "model": "Emtec X150 120gb", "serialNumber": "LDS645R002202", "variant": "5.0", "size": 120034.123776, "interface": "ATA"}, {"type": "Display", "model": "Lcd Monitor", "manufacturer": "Auo", "productionDate": "2012-01-01T00:00:00", "size": 15.529237982414482, "technology": "LCD", "resolutionWidth": 1366, "resolutionHeight": 768, "refreshRate": 60}, {"type": "GraphicCard", "model": "4th Gen Core Processor Integrated Graphics Controller", "manufacturer": "Intel Corporation"}, {"type": "Motherboard", "model": "1993", "manufacturer": "Hewlett-Packard", "serialNumber": "PEBJK001X5ZI3Z", "version": "L77 Ver. 01.05", "slots": 2, "usb": 3, "firewire": 0, "serial": 1, "pcmcia": 0, "biosDate": "2014-04-28T22:00:00.000Z", "ramSlots": 2, "ramMaxSize": 16}], "device": {"type": "Laptop", "actions": [{"type": "BenchmarkRamSysbench", "elapsed": 1, "rate": 0.731}], "model": "Hp Probook 650 G1", "manufacturer": "Hewlett-Packard", "serialNumber": "CNU406CLGR", "version": "A3009DD10303", "sku": "H5G75EA#ABE", "chassis": "Netbook"}, "closed": true, "endTime": "2022-06-09T12:10:50.809Z", "uuid": "7928afeb-e6a4-464a-a842-0c3de0d01677", "software": "Workbench", "version": "12.0b0", "elapsed": 34}
diff --git a/lot/migrations/0001_initial.py b/lot/migrations/0001_initial.py
index 35ca297..cb398b2 100644
--- a/lot/migrations/0001_initial.py
+++ b/lot/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 5.0.6 on 2024-07-08 13:55
+# Generated by Django 5.0.6 on 2024-07-17 14:57
import django.db.models.deletion
from django.conf import settings
@@ -10,11 +10,33 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
- ("device", "0003_remove_component_type_remove_computer_type_and_more"),
+ ("device", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
+ migrations.CreateModel(
+ name="LotTag",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=64)),
+ (
+ "owner",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ],
+ ),
migrations.CreateModel(
name="Lot",
fields=[
@@ -29,18 +51,6 @@ class Migration(migrations.Migration):
),
("created", models.DateTimeField(auto_now_add=True)),
("updated", models.DateTimeField(auto_now=True)),
- (
- "type",
- models.CharField(
- choices=[
- ("Incoming", "Incoming"),
- ("Outgoing", "Outgoing"),
- ("Temporal", "Temporal"),
- ],
- default="Temporal",
- max_length=32,
- ),
- ),
("name", models.CharField(blank=True, max_length=64, null=True)),
("code", models.CharField(blank=True, max_length=64, null=True)),
("description", models.CharField(blank=True, max_length=64, null=True)),
@@ -53,6 +63,12 @@ class Migration(migrations.Migration):
to=settings.AUTH_USER_MODEL,
),
),
+ (
+ "type",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE, to="lot.lottag"
+ ),
+ ),
],
),
]
diff --git a/lot/models.py b/lot/models.py
index 860bdbf..fb34778 100644
--- a/lot/models.py
+++ b/lot/models.py
@@ -1,41 +1,31 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
-from utils.constants import STR_SM_SIZE, STR_SIZE
+from utils.constants import (
+ STR_SM_SIZE,
+ STR_SIZE,
+ STR_EXTEND_SIZE,
+)
from user.models import User
from device.models import Device
+from snapshot.models import Annotation
+
+
+class LotTag(models.Model):
+ name = models.CharField(max_length=STR_SIZE, blank=False, null=False)
+ owner = models.ForeignKey(User, on_delete=models.CASCADE)
+
+ def __str__(self):
+ return self.name
class Lot(models.Model):
- class Types(models.TextChoices):
- INCOMING = "Incoming"
- OUTGOING = "Outgoing"
- TEMPORAL = "Temporal"
-
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
- type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.TEMPORAL)
name = models.CharField(max_length=STR_SIZE, blank=True, null=True)
code = models.CharField(max_length=STR_SIZE, blank=True, null=True)
description = models.CharField(max_length=STR_SIZE, blank=True, null=True)
closed = models.BooleanField(default=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
+ type = models.ForeignKey(LotTag, on_delete=models.CASCADE)
devices = models.ManyToManyField(Device)
-
- @property
- def is_incoming(self):
- if self.type == self.Types.INCOMING:
- return True
- return False
-
- @property
- def is_outgoing(self):
- if self.type == self.Types.OUTGOING:
- return True
- return False
-
- @property
- def is_temporal(self):
- if self.type == self.Types.TEMPORAL:
- return True
- return False
diff --git a/lot/templates/list_lots.html b/lot/templates/list_lots.html
index 126e7bb..d11fb3c 100644
--- a/lot/templates/list_lots.html
+++ b/lot/templates/list_lots.html
@@ -11,50 +11,21 @@
diff --git a/lot/urls.py b/lot/urls.py
index 25f89ef..691e592 100644
--- a/lot/urls.py
+++ b/lot/urls.py
@@ -9,7 +9,5 @@ urlpatterns = [
path("edit//", views.EditLotView.as_view(), name="edit"),
path("add/devices/", views.AddToLotView.as_view(), name="add_devices"),
path("del/devices/", views.DelToLotView.as_view(), name="del_devices"),
- path("temporal/", views.LotsTemporalView.as_view(), name="lots_temporal"),
- path("outgoing/", views.LotsOutgoingView.as_view(), name="lots_outgoing"),
- path("incoming/", views.LotsIncomingView.as_view(), name="lots_incoming"),
+ path("tag//", views.LotsTagsView.as_view(), name="tag"),
]
diff --git a/lot/views.py b/lot/views.py
index 59c46f2..44d7266 100644
--- a/lot/views.py
+++ b/lot/views.py
@@ -9,7 +9,7 @@ from django.views.generic.edit import (
FormView
)
from dashboard.mixins import DashboardView
-from lot.models import Lot
+from lot.models import Lot, LotTag
from lot.forms import LotsForm
@@ -84,20 +84,15 @@ class AddToLotView(DashboardView, FormView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
lots = Lot.objects.filter(owner=self.request.user)
- lots_incoming = lots.filter(type=Lot.Types.INCOMING).exists()
- lots_outgoing = lots.filter(type=Lot.Types.OUTGOING).exists()
- lots_temporal = lots.filter(type=Lot.Types.TEMPORAL).exists()
+ lot_tags = LotTag.objects.filter(owner=self.request.user)
context.update({
'lots': lots,
- 'incoming': lots_incoming,
- 'outgoing': lots_outgoing,
- 'temporal': lots_temporal
+ 'lot_tags':lot_tags,
})
return context
def get_form(self):
form = super().get_form()
- # import pdb; pdb.set_trace()
form.fields["lots"].queryset = Lot.objects.filter(owner=self.request.user)
return form
@@ -119,28 +114,23 @@ class DelToLotView(AddToLotView):
return response
-class LotsTemporalView(DashboardView, TemplateView):
+class LotsTagsView(DashboardView, TemplateView):
template_name = "lots.html"
- title = _("Temporal lots")
- breadcrumb = "lot / temporal lots"
+ title = _("lots")
+ breadcrumb = _("lots") + " /"
success_url = reverse_lazy('dashboard:unassigned_devices')
- lot_type = Lot.Types.TEMPORAL
def get_context_data(self, **kwargs):
+ self.pk = kwargs.get('pk')
context = super().get_context_data(**kwargs)
- lots = Lot.objects.filter(owner=self.request.user)
+ tag = get_object_or_404(LotTag, owner=self.request.user, id=self.pk)
+ self.title += " {}".format(tag.name)
+ self.breadcrumb += " {}".format(tag.name)
+ lots = Lot.objects.filter(owner=self.request.user).filter(type=tag)
context.update({
- 'lots': lots.filter(type=self.lot_type),
+ 'lots': lots,
+ 'title': self.title,
+ 'breadcrumb': self.breadcrumb
})
return context
-class LotsOutgoingView(LotsTemporalView):
- title = _("Outgoing lots")
- breadcrumb = "lot / outging lots"
- lot_type = Lot.Types.OUTGOING
-
-
-class LotsIncomingView(LotsTemporalView):
- title = _("Incoming lots")
- breadcrumb = "lot / Incoming lots"
- lot_type = Lot.Types.INCOMING
diff --git a/reset.sh b/reset.sh
new file mode 100644
index 0000000..a3bd06b
--- /dev/null
+++ b/reset.sh
@@ -0,0 +1,4 @@
+rm db/*
+./manage.py migrate
+./manage.py add_user user@example.org 1234
+./manage.py up_snapshots example/ user@example.org
diff --git a/snapshot/migrations/0001_initial.py b/snapshot/migrations/0001_initial.py
index 8fce7e2..206cc8a 100644
--- a/snapshot/migrations/0001_initial.py
+++ b/snapshot/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 5.0.6 on 2024-06-11 09:20
+# Generated by Django 5.0.6 on 2024-07-17 14:57
import django.db.models.deletion
from django.conf import settings
@@ -16,7 +16,7 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name="Snapshot",
+ name="Annotation",
fields=[
(
"id",
@@ -28,39 +28,17 @@ class Migration(migrations.Migration):
),
),
("created", models.DateTimeField(auto_now_add=True)),
- (
- "software",
- models.CharField(
- choices=[("Workbench", "Workbench")],
- default="Workbench",
- max_length=32,
- ),
- ),
("uuid", models.UUIDField()),
- ("version", models.CharField(max_length=32)),
- ("sid", models.CharField(max_length=32)),
- ("settings_version", models.CharField(max_length=32)),
- ("is_server_erase", models.BooleanField(default=False)),
(
- "severity",
- models.SmallIntegerField(
- choices=[
- (0, "Info"),
- (1, "Notice"),
- (2, "Warning"),
- (3, "Error"),
- ],
- default=0,
- ),
+ "type",
+ models.SmallIntegerField(choices=[(0, "System"), (1, "User")]),
),
- ("start_time", models.DateTimeField()),
- ("end_time", models.DateTimeField()),
- ("components", models.ManyToManyField(to="device.component")),
+ ("key", models.CharField(max_length=256)),
+ ("value", models.CharField(max_length=256)),
(
- "computer",
+ "device",
models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to="device.computer",
+ on_delete=django.db.models.deletion.CASCADE, to="device.device"
),
),
(
@@ -72,4 +50,10 @@ class Migration(migrations.Migration):
),
],
),
+ migrations.AddConstraint(
+ model_name="annotation",
+ constraint=models.UniqueConstraint(
+ fields=("type", "key", "uuid"), name="unique_type_key_uuid"
+ ),
+ ),
]
diff --git a/snapshot/migrations/0002_alter_snapshot_uuid.py b/snapshot/migrations/0002_alter_snapshot_uuid.py
deleted file mode 100644
index e833d88..0000000
--- a/snapshot/migrations/0002_alter_snapshot_uuid.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 5.0.6 on 2024-07-11 14:16
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("snapshot", "0001_initial"),
- ]
-
- operations = [
- migrations.AlterField(
- model_name="snapshot",
- name="uuid",
- field=models.UUIDField(unique=True),
- ),
- ]
diff --git a/snapshot/migrations/0003_remove_snapshot_start_time.py b/snapshot/migrations/0003_remove_snapshot_start_time.py
deleted file mode 100644
index cedcccc..0000000
--- a/snapshot/migrations/0003_remove_snapshot_start_time.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 5.0.6 on 2024-07-11 14:18
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("snapshot", "0002_alter_snapshot_uuid"),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name="snapshot",
- name="start_time",
- ),
- ]
diff --git a/snapshot/migrations/0004_anotation.py b/snapshot/migrations/0004_anotation.py
deleted file mode 100644
index f2e6887..0000000
--- a/snapshot/migrations/0004_anotation.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Generated by Django 5.0.6 on 2024-07-15 09:20
-
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("snapshot", "0003_remove_snapshot_start_time"),
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name="anotation",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- ("created", models.DateTimeField(auto_now_add=True)),
- ("uuid", models.UUIDField(unique=True)),
- ("key", models.CharField(max_length=256)),
- ("value", models.CharField(max_length=256)),
- (
- "owner",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to=settings.AUTH_USER_MODEL,
- ),
- ),
- ],
- ),
- ]
diff --git a/snapshot/migrations/0005_annotation_delete_anotation.py b/snapshot/migrations/0005_annotation_delete_anotation.py
deleted file mode 100644
index 10c2ded..0000000
--- a/snapshot/migrations/0005_annotation_delete_anotation.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Generated by Django 5.0.6 on 2024-07-15 09:21
-
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("snapshot", "0004_anotation"),
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name="Annotation",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- ("created", models.DateTimeField(auto_now_add=True)),
- ("uuid", models.UUIDField(unique=True)),
- ("key", models.CharField(max_length=256)),
- ("value", models.CharField(max_length=256)),
- (
- "owner",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to=settings.AUTH_USER_MODEL,
- ),
- ),
- ],
- ),
- migrations.DeleteModel(
- name="anotation",
- ),
- ]
diff --git a/snapshot/models.py b/snapshot/models.py
index 868b25a..bb6e40e 100644
--- a/snapshot/models.py
+++ b/snapshot/models.py
@@ -1,39 +1,76 @@
+import json
+
from django.db import models
+
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
+from snapshot.xapian import search
from user.models import User
-from device.models import Computer, Component
-
-# Create your models here.
-class Snapshot(models.Model):
- class SoftWare(models.TextChoices):
- WORKBENCH= "Workbench"
+class Snapshot:
+ def __init__(self, uuid):
+ self.uuid = uuid
+ self.owner = None
+ self.doc = None
+ self.created = None
+ self.annotations = []
- class Severity(models.IntegerChoices):
- Info = 0, "Info"
- Notice = 1, "Notice"
- Warning = 2, "Warning"
- Error = 3, "Error"
+ self.get_owner()
+ self.get_time()
- created = models.DateTimeField(auto_now_add=True)
- software = models.CharField(max_length=STR_SM_SIZE, choices=SoftWare, default=SoftWare.WORKBENCH)
- uuid = models.UUIDField(unique=True)
- version = models.CharField(max_length=STR_SM_SIZE)
- sid = models.CharField(max_length=STR_SM_SIZE)
- settings_version = models.CharField(max_length=STR_SM_SIZE)
- is_server_erase = models.BooleanField(default=False)
- severity = models.SmallIntegerField(choices=Severity, default=Severity.Info)
- end_time = models.DateTimeField()
- owner = models.ForeignKey(User, on_delete=models.CASCADE)
- computer = models.ForeignKey(Computer, on_delete=models.CASCADE)
- components = models.ManyToManyField(Component)
+ def get_annotations(self):
+ self.annotations = Annotation.objects.filter(
+ uuid=self.uuid
+ ).order_by("created")
+
+ def get_owner(self):
+ if not self.annotations:
+ self.get_annotations()
+ a = self.annotations.first()
+ if a:
+ self.owner = a.owner
+
+ def get_doc(self):
+ self.doc = {}
+ qry = 'uuid:"{}"'.format(self.uuid)
+ matches = search(qry, limit=1)
+ if matches.size() < 0:
+ return
+
+ for xa in matches:
+ self.doc = json.loads(xa.document.get_data())
+
+ def get_time(self):
+ if not self.doc:
+ self.get_doc()
+ self.created = self.doc.get("endTime")
+
+ if not self.created:
+ self.created = self.annotations.last().created
+
+ def components(self):
+ return self.doc.get('components', [])
class Annotation(models.Model):
+ class Type(models.IntegerChoices):
+ SYSTEM= 0, "System"
+ USER = 1, "User"
+
created = models.DateTimeField(auto_now_add=True)
- uuid = models.UUIDField(unique=True)
+ uuid = models.UUIDField()
owner = models.ForeignKey(User, on_delete=models.CASCADE)
+ type = models.SmallIntegerField(choices=Type)
key = models.CharField(max_length=STR_EXTEND_SIZE)
value = models.CharField(max_length=STR_EXTEND_SIZE)
+ device = models.ForeignKey('device.Device', on_delete=models.CASCADE)
+ class Meta:
+ constraints = [
+ models.UniqueConstraint(fields=["type", "key", "uuid"], name="unique_type_key_uuid")
+ ]
+
+ def is_user_annotation(self):
+ if self.type == self.Type.USER:
+ return True
+ return False
diff --git a/snapshot/parse.py b/snapshot/parse.py
index f6ce559..ea7e0a5 100644
--- a/snapshot/parse.py
+++ b/snapshot/parse.py
@@ -5,42 +5,25 @@ import xapian
import hashlib
from datetime import datetime
+from snapshot.xapian import search, index
from snapshot.models import Snapshot, Annotation
-from snapshot.xapian import search, indexer, database
-
-
-HID_ALGO1 = [
- "manufacturer",
- "model",
- "chassis",
- "serialNumber",
- "sku"
-]
+from device.models import Device
+from utils.constants import ALGOS
class Build:
def __init__(self, snapshot_json, user):
self.json = snapshot_json
+ self.uuid = self.json['uuid']
self.user = user
self.hid = None
self.index()
- self.create_annotation()
+ self.create_annotations()
def index(self):
- matches = search(self.json['uuid'], limit=1)
- if matches.size() > 0:
- return
-
snap = json.dumps(self.json)
- doc = xapian.Document()
- doc.set_data(snap)
-
- indexer.set_document(doc)
- indexer.index_text(snap)
-
- # Add the document to the database.
- database.add_document(doc)
+ index(self.uuid, snap)
def get_hid_14(self):
device = self.json['device']
@@ -52,15 +35,35 @@ class Build:
hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}"
return hashlib.sha3_256(hid.encode()).hexdigest()
- def create_annotation(self):
- uuid = self.json['uuid']
- owner = self.user
- key = 'hidalgo1'
- value = self.get_hid_14()
- Annotation.objects.create(
- uuid=uuid,
- owner=owner,
- key=key,
- value=value
- )
+ def create_annotations(self):
+ algorithms = {
+ 'hidalgo1': self.get_hid_14(),
+ }
+
+ annotation = Annotation.objects.filter(
+ owner=self.user,
+ type=Annotation.Type.SYSTEM,
+ key='hidalgo1',
+ value = algorithms['hidalgo1']
+ ).first()
+
+ if annotation:
+ device = annotation.device
+ else:
+ device = Device.objects.create(
+ type=self.json["device"]["type"],
+ manufacturer=self.json["device"]["manufacturer"],
+ model=self.json["device"]["model"],
+ owner=self.user
+ )
+
+ for k, v in algorithms.items():
+ Annotation.objects.create(
+ uuid=self.uuid,
+ owner=self.user,
+ device=device,
+ type=Annotation.Type.SYSTEM,
+ key=k,
+ value=v
+ )
diff --git a/snapshot/views.py b/snapshot/views.py
index 0b143a9..b49615c 100644
--- a/snapshot/views.py
+++ b/snapshot/views.py
@@ -2,9 +2,13 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic.base import TemplateView
from django.views.generic.edit import FormView
from django.urls import reverse_lazy
+from django.views.generic.edit import (
+ CreateView,
+ UpdateView,
+)
from dashboard.mixins import DashboardView
-from snapshot.models import Snapshot
+from snapshot.models import Snapshot, Annotation
# from snapshot.forms import UploadForm
# from django.shortcuts import render
# from rest_framework import viewsets
@@ -24,7 +28,8 @@ class ListSnapshotsView(DashboardView, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- snapshots = Snapshot.objects.filter(owner=self.request.user)
+ # snapshots = Snapshot.objects.filter(owner=self.request.user)
+ snapshots = []
context.update({
'snapshots': snapshots,
})
diff --git a/snapshot/xapian.py b/snapshot/xapian.py
index 8ed6261..222afe3 100644
--- a/snapshot/xapian.py
+++ b/snapshot/xapian.py
@@ -1,22 +1,51 @@
import xapian
-database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
+# database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
-indexer = xapian.TermGenerator()
-stemmer = xapian.Stem("english")
-indexer.set_stemmer(stemmer)
+# Read Only
+# database = xapian.Database("db")
+
+# indexer = xapian.TermGenerator()
+# stemmer = xapian.Stem("english")
+# indexer.set_stemmer(stemmer)
def search(qs, offset=0, limit=10):
- query_string = str.join(' ', qs)
+ database = xapian.Database("db")
qp = xapian.QueryParser()
- qp.set_stemmer(stemmer)
qp.set_database(database)
+ qp.set_stemmer(xapian.Stem("english"))
qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME)
- query = qp.parse_query(query_string)
+ qp.add_prefix("uuid", "uuid")
+ # qp.add_prefix("snapshot", "snapshot")
+ query = qp.parse_query(qs)
enquire = xapian.Enquire(database)
enquire.set_query(query)
matches = enquire.get_mset(offset, limit)
return matches
+
+def index(uuid, snap):
+ uuid = 'uuid:"{}"'.format(uuid)
+ try:
+ matches = search(uuid, limit=1)
+ if matches.size() > 0:
+ return
+ except xapian.DatabaseNotFoundError:
+ pass
+
+ database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
+ indexer = xapian.TermGenerator()
+ stemmer = xapian.Stem("english")
+ indexer.set_stemmer(stemmer)
+
+ doc = xapian.Document()
+ doc.set_data(snap)
+
+ indexer.set_document(doc)
+ indexer.index_text(snap)
+ indexer.index_text(uuid, 10, "uuid")
+ # indexer.index_text(snap, 1, "snapshot")
+
+ database.add_document(doc)
diff --git a/user/management/commands/add_user.py b/user/management/commands/add_user.py
index 5e3222c..d9bb0a4 100644
--- a/user/management/commands/add_user.py
+++ b/user/management/commands/add_user.py
@@ -1,5 +1,6 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
+from lot.models import LotTag
User = get_user_model()
@@ -16,8 +17,21 @@ class Command(BaseCommand):
email = kwargs['email']
password = kwargs['password']
self.create_user(email, password)
+ self.create_lot_tags()
def create_user(self, email, password):
- u = User.objects.create(email=email, password=password)
- u.set_password(password)
- u.save()
+ self.u = User.objects.create(email=email, password=password)
+ self.u.set_password(password)
+ self.u.save()
+
+ def create_lot_tags(self):
+ tags = [
+ "Entrada",
+ "Salida",
+ "Temporal"
+ ]
+ for tag in tags:
+ LotTag.objects.create(
+ name=tag,
+ owner=self.u
+ )
diff --git a/user/migrations/0001_initial.py b/user/migrations/0001_initial.py
index aa08fe8..7faf363 100644
--- a/user/migrations/0001_initial.py
+++ b/user/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 5.0.6 on 2024-06-11 09:19
+# Generated by Django 5.0.6 on 2024-07-17 14:57
from django.db import migrations, models
diff --git a/utils/constants.py b/utils/constants.py
index 210b1c2..2fd9a13 100644
--- a/utils/constants.py
+++ b/utils/constants.py
@@ -6,3 +6,17 @@ STR_SM_SIZE = 32
STR_SIZE = 64
STR_BIG_SIZE = 128
STR_EXTEND_SIZE = 256
+
+
+# Algorithms for build hids
+HID_ALGO1 = [
+ "manufacturer",
+ "model",
+ "chassis",
+ "serialNumber",
+ "sku"
+]
+
+ALGOS = {
+ "hidalgo1": HID_ALGO1,
+}