diff --git a/apps/taxonomy/admin.py b/apps/taxonomy/admin.py
index acc99e8..5c33b95 100644
--- a/apps/taxonomy/admin.py
+++ b/apps/taxonomy/admin.py
@@ -1,6 +1,6 @@
from django.contrib import admin
-from .models import Category, LabPriority, Project, Tag, WorkGroup
+from .models import Category, EntryType, LabPriority, Project, Tag, WorkGroup
@admin.register(Project)
@@ -19,6 +19,14 @@ class CategoryAdmin(admin.ModelAdmin):
search_fields = ('name', 'short_code')
+@admin.register(EntryType)
+class EntryTypeAdmin(admin.ModelAdmin):
+ list_display = ('name', 'short_code', 'slug', 'is_active', 'sort_order')
+ list_editable = ('is_active', 'sort_order')
+ prepopulated_fields = {'slug': ('name',)}
+ search_fields = ('name', 'short_code')
+
+
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
list_display = ('name', 'use_count')
diff --git a/apps/taxonomy/forms.py b/apps/taxonomy/forms.py
index ef9e656..e173b75 100644
--- a/apps/taxonomy/forms.py
+++ b/apps/taxonomy/forms.py
@@ -1,6 +1,6 @@
from django import forms
-from .models import Category, LabPriority, Project, WorkGroup
+from .models import Category, EntryType, LabPriority, Project, WorkGroup
class ProjectForm(forms.ModelForm):
@@ -21,6 +21,15 @@ class Meta:
}
+class EntryTypeForm(forms.ModelForm):
+ class Meta:
+ model = EntryType
+ fields = ['name', 'short_code', 'is_active', 'sort_order']
+ widgets = {
+ 'sort_order': forms.NumberInput(attrs={'min': 0}),
+ }
+
+
class WorkGroupForm(forms.ModelForm):
class Meta:
model = WorkGroup
diff --git a/apps/taxonomy/management/commands/seed_taxonomy.py b/apps/taxonomy/management/commands/seed_taxonomy.py
index 132dc03..2e1d6c4 100644
--- a/apps/taxonomy/management/commands/seed_taxonomy.py
+++ b/apps/taxonomy/management/commands/seed_taxonomy.py
@@ -1,6 +1,6 @@
from django.core.management.base import BaseCommand
-from apps.taxonomy.models import Category, LabPriority, Project
+from apps.taxonomy.models import Category, EntryType, LabPriority, Project
PROJECTS = [
{'name': 'DUNE', 'short_code': 'DUNE', 'sort_order': 10},
@@ -17,6 +17,12 @@
{'name': 'Training', 'short_code': 'TRN', 'sort_order': 40},
]
+ENTRY_TYPES = [
+ {'name': 'Weekly Report', 'short_code': 'WEEKLY', 'sort_order': 10},
+ {'name': 'Milestone', 'short_code': 'MILESTONE', 'sort_order': 20},
+ {'name': 'Activity', 'short_code': 'ACTIVITY', 'sort_order': 30},
+]
+
LAB_PRIORITIES = [
{'name': 'Science Mission', 'short_code': 'SCI-MISS', 'sort_order': 10},
{'name': 'DUNE/LBNF', 'short_code': 'DUNE', 'sort_order': 20},
@@ -46,6 +52,14 @@ def handle(self, *args, **options):
status = 'created' if created else 'exists '
self.stdout.write(f' [{status}] {name}')
+ self.stdout.write('Seeding entry types…')
+ for data in ENTRY_TYPES:
+ name = data['name']
+ defaults = {k: v for k, v in data.items() if k != 'name'}
+ _, created = EntryType.objects.get_or_create(name=name, defaults=defaults)
+ status = 'created' if created else 'exists '
+ self.stdout.write(f' [{status}] {name}')
+
self.stdout.write('Seeding lab priorities…')
for data in LAB_PRIORITIES:
name = data['name']
diff --git a/apps/taxonomy/migrations/0004_entrytype.py b/apps/taxonomy/migrations/0004_entrytype.py
new file mode 100644
index 0000000..436d050
--- /dev/null
+++ b/apps/taxonomy/migrations/0004_entrytype.py
@@ -0,0 +1,41 @@
+# Generated by Django 5.2.14 on 2026-06-25 17:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("taxonomy", "0003_labpriority"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="EntryType",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("name", models.CharField(max_length=100, unique=True)),
+ ("slug", models.SlugField(blank=True, max_length=100, unique=True)),
+ ("short_code", models.CharField(blank=True, max_length=20)),
+ ("is_active", models.BooleanField(db_index=True, default=True)),
+ (
+ "sort_order",
+ models.PositiveSmallIntegerField(db_index=True, default=0),
+ ),
+ ],
+ options={
+ "verbose_name": "Entry Type",
+ "verbose_name_plural": "Entry Types",
+ "ordering": ["sort_order", "name"],
+ "abstract": False,
+ },
+ ),
+ ]
diff --git a/apps/taxonomy/models.py b/apps/taxonomy/models.py
index 8cba0d2..600bdb7 100644
--- a/apps/taxonomy/models.py
+++ b/apps/taxonomy/models.py
@@ -32,6 +32,12 @@ class Meta(TaxonomyBase.Meta):
verbose_name_plural = 'categories'
+class EntryType(TaxonomyBase):
+ class Meta(TaxonomyBase.Meta):
+ verbose_name = 'Entry Type'
+ verbose_name_plural = 'Entry Types'
+
+
class WorkGroup(TaxonomyBase):
class Meta(TaxonomyBase.Meta):
verbose_name = 'Group'
diff --git a/apps/taxonomy/templates/taxonomy/categories.html b/apps/taxonomy/templates/taxonomy/categories.html
index a0789c3..676500a 100644
--- a/apps/taxonomy/templates/taxonomy/categories.html
+++ b/apps/taxonomy/templates/taxonomy/categories.html
@@ -15,6 +15,8 @@
Taxonomy
class="px-4 py-2 text-sm font-medium text-slate-500 hover:text-slate-700 border-b-2 border-transparent -mb-px">Projects
Categories
+
Entry Types
Groups
+
+
+
+
+{% endblock %}
diff --git a/apps/taxonomy/templates/taxonomy/entry_types.html b/apps/taxonomy/templates/taxonomy/entry_types.html
new file mode 100644
index 0000000..33c6c85
--- /dev/null
+++ b/apps/taxonomy/templates/taxonomy/entry_types.html
@@ -0,0 +1,129 @@
+{% extends "base.html" %}
+{% block title %}Entry Types — SCD Reporting{% endblock %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/apps/taxonomy/templates/taxonomy/groups.html b/apps/taxonomy/templates/taxonomy/groups.html
index 76d9707..fd6962c 100644
--- a/apps/taxonomy/templates/taxonomy/groups.html
+++ b/apps/taxonomy/templates/taxonomy/groups.html
@@ -15,6 +15,8 @@
class="px-4 py-2 text-sm font-medium text-slate-500 hover:text-slate-700 border-b-2 border-transparent -mb-px">Projects