diff --git a/db.sqlite3 b/db.sqlite3 index dd31c09..4121ae1 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/sheets/admin.py b/sheets/admin.py index c6fe108..7f2c5ce 100644 --- a/sheets/admin.py +++ b/sheets/admin.py @@ -1,2 +1,45 @@ from django.contrib import admin +from .models import Client # Only import Client +from .models import SecondTableEntry +# Register only the Client model +@admin.register(Client) +class ClientAdmin(admin.ModelAdmin): + list_display = ('name', 'address') + search_fields = ('name',) + + # Optional: Customize the add form fields + fields = ['name', 'address'] + +@admin.register(SecondTableEntry) +class SecondTableEntryAdmin(admin.ModelAdmin): + list_display = ('id', 'client', 'date', 'is_warm', 'lhe_output_short', 'notes_preview') + list_display_links = ('id', 'client') # Fields that link to edit page + list_editable = ('is_warm',) + list_filter = ('is_warm', 'client') + search_fields = ('client__name', 'notes') + date_hierarchy = 'date' + ordering = ('-date',) + + fieldsets = ( + (None, { + 'fields': ('client', 'date') + }), + ('LHe Data', { + 'fields': ('is_warm', 'lhe_delivery', 'lhe_output'), + 'description': 'Enter all liquid helium measurements' + }), + ('Additional Info', { + 'fields': ('notes',), + 'classes': ('collapse',) + }) + ) + + # Custom display methods + def lhe_output_short(self, obj): + return f"{obj.lhe_output} L" if obj.lhe_output else "-" + lhe_output_short.short_description = 'Output' + + def notes_preview(self, obj): + return obj.notes[:30] + '...' if obj.notes else "" + notes_preview.short_description = 'Notes Preview' \ No newline at end of file diff --git a/sheets/migrations/0002_remove_secondtableentry_age_and_more.py b/sheets/migrations/0002_remove_secondtableentry_age_and_more.py new file mode 100644 index 0000000..eaab916 --- /dev/null +++ b/sheets/migrations/0002_remove_secondtableentry_age_and_more.py @@ -0,0 +1,47 @@ +# Generated by Django 5.2.1 on 2025-07-08 12:13 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sheets', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='secondtableentry', + name='age', + ), + migrations.RemoveField( + model_name='secondtableentry', + name='email', + ), + migrations.AddField( + model_name='secondtableentry', + name='date', + field=models.DateField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='secondtableentry', + name='is_warm', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='secondtableentry', + name='lhe_delivery', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='secondtableentry', + name='lhe_output', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='secondtableentry', + name='notes', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/sheets/migrations/0003_alter_secondtableentry_lhe_output.py b/sheets/migrations/0003_alter_secondtableentry_lhe_output.py new file mode 100644 index 0000000..073b12a --- /dev/null +++ b/sheets/migrations/0003_alter_secondtableentry_lhe_output.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.1 on 2025-07-08 13:18 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sheets', '0002_remove_secondtableentry_age_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='secondtableentry', + name='lhe_output', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/sheets/migrations/0004_alter_secondtableentry_lhe_output.py b/sheets/migrations/0004_alter_secondtableentry_lhe_output.py new file mode 100644 index 0000000..9a6c3a2 --- /dev/null +++ b/sheets/migrations/0004_alter_secondtableentry_lhe_output.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.1 on 2025-07-08 13:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sheets', '0003_alter_secondtableentry_lhe_output'), + ] + + operations = [ + migrations.AlterField( + model_name='secondtableentry', + name='lhe_output', + field=models.CharField(blank=True, max_length=100, null=True), + ), + ] diff --git a/sheets/migrations/0005_alter_secondtableentry_lhe_output.py b/sheets/migrations/0005_alter_secondtableentry_lhe_output.py new file mode 100644 index 0000000..dffa88b --- /dev/null +++ b/sheets/migrations/0005_alter_secondtableentry_lhe_output.py @@ -0,0 +1,19 @@ +# Generated by Django 5.2.1 on 2025-07-08 13:36 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sheets', '0004_alter_secondtableentry_lhe_output'), + ] + + operations = [ + migrations.AlterField( + model_name='secondtableentry', + name='lhe_output', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/sheets/migrations/0006_remove_excelentry_age_remove_excelentry_email_and_more.py b/sheets/migrations/0006_remove_excelentry_age_remove_excelentry_email_and_more.py new file mode 100644 index 0000000..105ed6f --- /dev/null +++ b/sheets/migrations/0006_remove_excelentry_age_remove_excelentry_email_and_more.py @@ -0,0 +1,43 @@ +# Generated by Django 5.2.1 on 2025-07-09 11:15 + +import django.core.validators +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sheets', '0005_alter_secondtableentry_lhe_output'), + ] + + operations = [ + migrations.RemoveField( + model_name='excelentry', + name='age', + ), + migrations.RemoveField( + model_name='excelentry', + name='email', + ), + migrations.AddField( + model_name='excelentry', + name='date', + field=models.DateField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='excelentry', + name='notes', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='excelentry', + name='pressure', + field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)]), + ), + migrations.AddField( + model_name='excelentry', + name='purity', + field=models.DecimalField(decimal_places=2, default=0.0, max_digits=5, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100)]), + ), + ] diff --git a/sheets/models.py b/sheets/models.py index 130df7e..22cf221 100644 --- a/sheets/models.py +++ b/sheets/models.py @@ -1,4 +1,8 @@ from django.db import models +from django.utils import timezone +from django.core.validators import MinValueValidator, MaxValueValidator + + class Client(models.Model): name = models.CharField(max_length=100) @@ -9,12 +13,39 @@ class Client(models.Model): class ExcelEntry(models.Model): client = models.ForeignKey(Client, on_delete=models.CASCADE) - age = models.IntegerField() - email = models.EmailField() + date = models.DateField(default=timezone.now) + pressure = models.DecimalField( + max_digits=10, + decimal_places=2, + validators=[MinValueValidator(0)], + default=0.00 + ) + purity = models.DecimalField( + max_digits=5, + decimal_places=2, + validators=[MinValueValidator(0), MaxValueValidator(100)], + default=0.00 + ) + notes = models.TextField(blank=True, null=True) date_joined = models.DateField(auto_now_add=True) + def __str__(self): + return f"{self.client.name} - {self.date}" + class SecondTableEntry(models.Model): client = models.ForeignKey(Client, on_delete=models.CASCADE) - age = models.IntegerField() - email = models.EmailField() + date = models.DateField(default=timezone.now) # Added default value + is_warm = models.BooleanField(default=False) + lhe_delivery = models.CharField(max_length=100, blank=True, null=True) + lhe_output = models.DecimalField( + max_digits=10, + decimal_places=2, + validators=[MinValueValidator(0)], + blank=True, + null=True + ) + notes = models.TextField(blank=True, null=True) date_joined = models.DateField(auto_now_add=True) + + def __str__(self): + return f"{self.client.name} - {self.date}" \ No newline at end of file diff --git a/sheets/templates/clients_table.html b/sheets/templates/clients_table.html index c79b444..8591a0c 100644 --- a/sheets/templates/clients_table.html +++ b/sheets/templates/clients_table.html @@ -1,290 +1,124 @@ - - - - - Clients Table - - - - - - +{% extends "base.html" %} +{% block content %} +
+ +
+ + +
-
-

Clients Table

- - - - - - - - - - - - - {% for client in clients %} - - - - - - - + +
# IDNameAddressActions
{{ forloop.counter }} {{ client.id }}{{ client.name }}{{ client.address }} - - -
+ + + + {% for month in months %} + {% endfor %} - -
Client{{ month }}
-
+ Total + + + + {% for data in monthly_data %} + + {{ data.client.name }} + {% for total in data.monthly_totals %} + {{ total|floatformat:2 }} + {% endfor %} + {{ data.year_total|floatformat:2 }} + + {% endfor %} + + - - - - - - -
- - + + +
+ + +{% endblock %} \ No newline at end of file diff --git a/sheets/templates/table_one.html b/sheets/templates/table_one.html index ece7b55..9df8de3 100644 --- a/sheets/templates/table_one.html +++ b/sheets/templates/table_one.html @@ -27,18 +27,32 @@ } table { width: 100%; + table-layout: fixed; border-collapse: collapse; - margin-top: 20px; } th, td { padding: 12px; - text-align: left; + text-align: center; border-bottom: 1px solid #ddd; } + th:nth-child(1), td:nth-child(1) { width: 5%; } /* # column */ + th:nth-child(2), td:nth-child(2) { width: 5%; } /* ID column */ + th:nth-child(3), td:nth-child(3) { width: 15%; } /* Client column */ + th:nth-child(4), td:nth-child(4) { width: 10%; } /* Entry 1 (Pressure) */ + th:nth-child(5), td:nth-child(5) { width: 10%; } /* Entry 2 (Purity) */ + th:nth-child(6), td:nth-child(6) { width: 15%; } /* Date Joined */ + th:nth-child(7), td:nth-child(7) { width: 25%; } /* Notes */ + th:nth-child(7), td:nth-child(7) { width: 30%; } /* Actions */ + + .actions { + white-space: nowrap; /* Prevent buttons from wrapping */ + } th { background-color: #007bff; color: white; font-weight: bold; + position: sticky; + top: 0; } tr:hover { background-color: #f1f1f1; @@ -106,6 +120,7 @@ .add-row-btn:hover { background-color: #0056b3; } + @@ -118,14 +133,25 @@
+ + + + + + + + + + - - + + + @@ -135,9 +161,10 @@ - - - + + + +
# ID ClientEntry 1Entry 2DruckReinheit Date JoinedNotes Actions
{{ forloop.counter }} {{ entry.id }} {{ entry.client.name }}{{ entry.age }}{{ entry.email }}{{ entry.date_joined }}{{ entry.pressure|floatformat:2 }}{{ entry.purity|floatformat:2 }}{{ entry.date_joined|date:"Y-m-d" }}{{ entry.notes|default:"" }} @@ -152,30 +179,72 @@ - - - -
- - - ⇦ Go to Clients + + -

Helium Output

- -
- - - - - {% for entry in entries_table2 %} - - - - - - - - - - {% endfor %} - -
#IDClientDateWarmLHe AnlieferungLHe AusgabeCommentsActions
{{ forloop.counter }}{{ entry.id }}{{ entry.client.name }}{{ entry.age }}{{ entry.email }}{{ entry.date_joined }} - - -
-
- - - -
- - -