feat: define core models
This commit is contained in:
parent
7dd8350cec
commit
4b4a85d1aa
|
@ -1,4 +1,86 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
from django.db.models.signals import post_migrate
|
||||||
|
|
||||||
|
|
||||||
|
def create_properties(sender, **kwargs):
|
||||||
|
from .models import Property
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Capacitance",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.QUANTITY,
|
||||||
|
"unit": "F",
|
||||||
|
"scale": -12,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Footprint",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.TEXT,
|
||||||
|
"unit": "",
|
||||||
|
"scale": 0,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="LCSC part number",
|
||||||
|
defaults={
|
||||||
|
"filterable": False,
|
||||||
|
"type": Property.Type.TEXT,
|
||||||
|
"unit": "",
|
||||||
|
"scale": 0,
|
||||||
|
"searchable": True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Inductance",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.QUANTITY,
|
||||||
|
"unit": "H",
|
||||||
|
"scale": -6,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Rated power",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.QUANTITY,
|
||||||
|
"unit": "W",
|
||||||
|
"scale": -4,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Rated voltage",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.QUANTITY,
|
||||||
|
"unit": "V",
|
||||||
|
"scale": -3,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Property.objects.get_or_create(
|
||||||
|
name="Resistance",
|
||||||
|
defaults={
|
||||||
|
"filterable": True,
|
||||||
|
"type": Property.Type.QUANTITY,
|
||||||
|
"unit": "Ω",
|
||||||
|
"scale": -3,
|
||||||
|
"searchable": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CoreConfig(AppConfig):
|
class CoreConfig(AppConfig):
|
||||||
|
@ -6,3 +88,6 @@ class CoreConfig(AppConfig):
|
||||||
label = "lelcsc_core"
|
label = "lelcsc_core"
|
||||||
name = "lelcsc.core"
|
name = "lelcsc.core"
|
||||||
verbose_name = "core"
|
verbose_name = "core"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
post_migrate.connect(create_properties, sender=self)
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
# Generated by Django 5.1.1 on 2024-09-16 22:00
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("lelcsc_core", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Component",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("part_number", models.CharField(max_length=30)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Property",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("name", models.CharField(max_length=50)),
|
||||||
|
(
|
||||||
|
"filterable",
|
||||||
|
models.BooleanField(
|
||||||
|
help_text="Whether this property can be used to filter components"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"type",
|
||||||
|
models.CharField(
|
||||||
|
choices=[("quantity", "Quantity"), ("text", "Text")],
|
||||||
|
max_length=8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"searchable",
|
||||||
|
models.BooleanField(
|
||||||
|
help_text="Whether this property should be used in search"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"unit",
|
||||||
|
models.CharField(
|
||||||
|
help_text="Symbol of this quantity's unit of measurement",
|
||||||
|
max_length=3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"scale",
|
||||||
|
models.SmallIntegerField(
|
||||||
|
help_text="Exponent of the smallest possible value"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Stock",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
("quantity", models.PositiveIntegerField()),
|
||||||
|
("original_quantity", models.PositiveIntegerField()),
|
||||||
|
("total_value", models.DecimalField(decimal_places=2, max_digits=8)),
|
||||||
|
("location", models.TextField()),
|
||||||
|
("owner_name", models.CharField(max_length=150)),
|
||||||
|
(
|
||||||
|
"component",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
|
to="lelcsc_core.component",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"owner",
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Value",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("text", models.TextField()),
|
||||||
|
("integer", models.BigIntegerField()),
|
||||||
|
(
|
||||||
|
"component",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="lelcsc_core.component",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"property",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="lelcsc_core.property",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"unique_together": {("component", "property")},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="component",
|
||||||
|
name="properties",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
through="lelcsc_core.Value", to="lelcsc_core.property"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,3 @@
|
||||||
|
from .auth import OIDCUser, User
|
||||||
|
from .component import Component, Property, Value
|
||||||
|
from .stock import Stock
|
|
@ -0,0 +1,62 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class Property(models.Model):
|
||||||
|
class Type(models.TextChoices):
|
||||||
|
QUANTITY = "quantity", _("Quantity")
|
||||||
|
TEXT = "text", _("Text")
|
||||||
|
|
||||||
|
name = models.CharField(max_length=50)
|
||||||
|
filterable = models.BooleanField(
|
||||||
|
help_text=_("Whether this property can be used to filter components")
|
||||||
|
)
|
||||||
|
type = models.CharField(choices=Type, max_length=8)
|
||||||
|
searchable = models.BooleanField(
|
||||||
|
help_text=_("Whether this property should be used in search")
|
||||||
|
)
|
||||||
|
unit = models.CharField(
|
||||||
|
max_length=3, help_text=_("Symbol of this quantity's unit of measurement")
|
||||||
|
)
|
||||||
|
scale = models.SmallIntegerField(
|
||||||
|
help_text=_("Exponent of the smallest possible value")
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
self.name + f" [{self.unit}]" if self.type == Property.Type.QUANTITY else ""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Component(models.Model):
|
||||||
|
part_number = models.CharField(max_length=30)
|
||||||
|
properties = models.ManyToManyField(Property, through="Value")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.part_number
|
||||||
|
|
||||||
|
|
||||||
|
class Value(models.Model):
|
||||||
|
class Meta:
|
||||||
|
unique_together = ("component", "property")
|
||||||
|
|
||||||
|
property = models.ForeignKey(Property, on_delete=models.CASCADE)
|
||||||
|
component = models.ForeignKey(Component, on_delete=models.CASCADE)
|
||||||
|
text = models.TextField()
|
||||||
|
integer = models.BigIntegerField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
match self.property.type:
|
||||||
|
case Property.Type.QUANTITY:
|
||||||
|
s = str(integer)
|
||||||
|
|
||||||
|
scale = self.property.scale
|
||||||
|
if scale > 0:
|
||||||
|
s += "0" * scale
|
||||||
|
elif scale < 0:
|
||||||
|
s = str(integer).rjust(abs(scale) + 1, "0")
|
||||||
|
s = s[:scale] + "." + s[scale:]
|
||||||
|
|
||||||
|
return f"{s} {self.property.unit}"
|
||||||
|
case Property.Type.TEXT:
|
||||||
|
return self.text
|
|
@ -0,0 +1,9 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class HasTimestamps(models.Model):
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
|
@ -0,0 +1,15 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from .auth import User
|
||||||
|
from .component import Component
|
||||||
|
from .mixins import HasTimestamps
|
||||||
|
|
||||||
|
|
||||||
|
class Stock(HasTimestamps):
|
||||||
|
component = models.ForeignKey(Component, on_delete=models.PROTECT)
|
||||||
|
quantity = models.PositiveIntegerField()
|
||||||
|
original_quantity = models.PositiveIntegerField()
|
||||||
|
total_value = models.DecimalField(max_digits=8, decimal_places=2)
|
||||||
|
location = models.TextField()
|
||||||
|
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
|
||||||
|
owner_name = models.CharField(max_length=150)
|
Loading…
Reference in New Issue