new update

This commit is contained in:
2025-08-28 12:22:27 +02:00
parent 16fd76ff5a
commit 70e055d20b
12 changed files with 970 additions and 591 deletions

Binary file not shown.

View File

@@ -1,2 +1,45 @@
from django.contrib import admin 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'

View File

@@ -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),
),
]

View File

@@ -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)]),
),
]

View File

@@ -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),
),
]

View File

@@ -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)]),
),
]

View File

@@ -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)]),
),
]

View File

@@ -1,4 +1,8 @@
from django.db import models from django.db import models
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator
class Client(models.Model): class Client(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
@@ -9,12 +13,39 @@ class Client(models.Model):
class ExcelEntry(models.Model): class ExcelEntry(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE) client = models.ForeignKey(Client, on_delete=models.CASCADE)
age = models.IntegerField() date = models.DateField(default=timezone.now)
email = models.EmailField() 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) date_joined = models.DateField(auto_now_add=True)
def __str__(self):
return f"{self.client.name} - {self.date}"
class SecondTableEntry(models.Model): class SecondTableEntry(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE) client = models.ForeignKey(Client, on_delete=models.CASCADE)
age = models.IntegerField() date = models.DateField(default=timezone.now) # Added default value
email = models.EmailField() 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) date_joined = models.DateField(auto_now_add=True)
def __str__(self):
return f"{self.client.name} - {self.date}"

View File

@@ -1,290 +1,124 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Clients Table</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f4f4f9;
}
.add-row-btn, .btn-go-back {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-bottom: 20px;
}
.add-row-btn:hover,
.btn-go-back:hover {
background-color: #0056b3;
}
.container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
h2 {
text-align: center;
color: #333;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #007bff;
color: white;
font-weight: bold;
}
tr:hover {
background-color: #f1f1f1;
}
.actions button {
margin: 2px;
padding: 5px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.edit-btn {
background-color: #28a745;
color: white;
}
.delete-btn {
background-color: #dc3545;
color: white;
}
.popup {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
}
.popup input {
display: block;
margin-bottom: 10px;
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.popup button {
margin-top: 10px;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.close-btn {
cursor: pointer;
float: right;
font-size: 18px;
color: #333;
}
</style>
</head>
<body>
{% block content %}
<div class="container">
<!-- Year Filter -->
<div class="year-filter">
<label for="year-select">Year:</label>
<select id="year-select" onchange="window.location.href='?year='+this.value">
{% for year in available_years %}
<option value="{{ year }}" {% if year == current_year %}selected{% endif %}>
{{ year }}
</option>
{% endfor %}
</select>
</div>
<div class="container"> <!-- Annual Summary Table -->
<h2>Clients Table</h2> <table class="summary-table">
<button class="add-row-btn" id="add-client">Add Client</button> <thead>
<table> <tr>
<thead> <th>Client</th>
<tr> {% for month in months %}
<th>#</th> <!-- This is your new sequential number column --> <th>{{ month }}</th>
<th>ID</th>
<th>Name</th>
<th>Address</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for client in clients %}
<tr data-id="{{ client.id }}">
<td>{{ forloop.counter }}</td> <!-- ← this gives you 1, 2, 3... -->
<td>{{ client.id }}</td>
<td>{{ client.name }}</td>
<td>{{ client.address }}</td>
<td class="actions">
<button class="edit-btn">Edit</button>
<button class="delete-btn">Delete</button>
</td>
</tr>
{% endfor %} {% endfor %}
</tbody> <th>Total</th>
</table> </tr>
</div> </thead>
<tbody>
{% for data in monthly_data %}
<tr>
<td>{{ data.client.name }}</td>
{% for total in data.monthly_totals %}
<td>{{ total|floatformat:2 }}</td>
{% endfor %}
<td class="total">{{ data.year_total|floatformat:2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Add Client Popup --> <!-- Navigation Buttons -->
<div id="add-popup" class="popup"> <div class="navigation-buttons">
<span class="close-btn">&times;</span> <a href="{% url 'table_one' %}" class="nav-button">
<h3>Add Client</h3> Go to Helium Input
<input type="text" id="add-name" placeholder="Name">
<input type="text" id="add-address" placeholder="Address">
<button id="save-add">Add</button>
</div>
<!-- Edit Client Popup -->
<div id="edit-popup" class="popup">
<span class="close-btn">&times;</span>
<h3>Edit Client</h3>
<input type="hidden" id="edit-id">
<input type="text" id="edit-name" placeholder="Name">
<input type="text" id="edit-address" placeholder="Address">
<button id="save-edit">Save</button>
</div>
<div style="margin-top: 30px; text-align: center;">
<a href="{% url 'table_one' %}">
<button class="add-row-btn">Go to Helium input</button>
</a> </a>
<a href="{% url 'table_two' %}"> <a href="{% url 'table_two' %}" class="nav-button">
<button class="add-row-btn">Go to Table output</button> Go to Helium Output
</a> </a>
</div> </div>
</div>
<style>
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.year-filter {
margin: 20px 0;
text-align: right;
}
.year-filter label {
margin-right: 10px;
}
.year-filter select {
padding: 5px;
border-radius: 4px;
border: 1px solid #ddd;
}
<script> .summary-table {
let currentModelName = "Client"; width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.summary-table th, .summary-table td {
padding: 10px;
text-align: center;
border: 1px solid #ddd;
}
.summary-table th {
background-color: #007bff;
color: white;
}
.summary-table tr:nth-child(even) {
background-color: #f9f9f9;
}
.summary-table tr:hover {
background-color: #f1f1f1;
}
.total {
font-weight: bold;
background-color: #e6f2ff;
}
// Open Add Popup .navigation-buttons {
$('#add-client').on('click', function () { display: flex;
$('#add-popup').fadeIn(); justify-content: center;
}); gap: 20px;
margin-top: 30px;
// Close Popups }
$('.close-btn').on('click', function () {
$('.popup').fadeOut(); .nav-button {
}); padding: 12px 24px;
background-color: #007bff;
// Save Add Client color: white;
$('#save-add').on('click', function () { text-decoration: none;
let name = $('#add-name').val(); border-radius: 4px;
let address = $('#add-address').val(); transition: background-color 0.3s;
}
$.ajax({
url: `/add-entry/Client/`, .nav-button:hover {
method: 'POST', background-color: #0056b3;
data: { }
'name': name, </style>
'address': address, {% endblock %}
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (response) {
let rowCount = $('tbody tr').length + 1;
let newRow = `
<tr data-id="${response.id}">
<td>${rowCount}</td>
<td>${response.id}</td>
<td>${response.name}</td>
<td>${response.address}</td>
<td class="actions">
<button class="edit-btn">Edit</button>
<button class="delete-btn">Delete</button>
</td>
</tr>
`;
$('tbody').append(newRow);
$('#add-popup').fadeOut();
},
error: function (xhr) {
alert('Failed to add client: ' + xhr.responseText);
}
});
});
// Open Edit Popup
$(document).on('click', '.edit-btn', function () {
let row = $(this).closest('tr');
$('#edit-id').val(row.data('id'));
$('#edit-name').val(row.find('td:eq(2)').text()); // Name
$('#edit-address').val(row.find('td:eq(3)').text()); // Address
$('#edit-popup').fadeIn();
});
// Save Edit Client
$('#save-edit').on('click', function () {
let id = $('#edit-id').val();
let name = $('#edit-name').val();
let address = $('#edit-address').val();
$.ajax({
url: `/update-entry/${currentModelName}/`,
method: 'POST',
data: {
'id': id,
'name': name,
'address': address,
'age': 0,
'email': 'none@example.com',
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (response) {
if (response.status === 'success') {
let row = $(`tr[data-id="${id}"]`);
row.find('td:eq(2)').text(name); // Correct column for Name
row.find('td:eq(3)').text(address); // Correct column for Address
$('#edit-popup').fadeOut();
}
}
});
});
// Delete Client
$(document).on('click', '.delete-btn', function () {
let row = $(this).closest('tr');
let id = row.data('id');
if (!confirm('Are you sure you want to delete this client?')) return;
$.ajax({
url: `/delete-entry/${currentModelName}/`,
method: 'POST',
data: {
'id': id,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (response) {
if (response.status === 'success') {
row.fadeOut(300, function () { $(this).remove(); });
} else {
alert('Delete failed: ' + response.message);
}
},
error: function (xhr, status, error) {
alert('Delete request failed:\n' + xhr.responseText);
console.log('Error:', error);
console.log('Status:', status);
}
});
});
</script>
</body>
</html>

View File

@@ -27,18 +27,32 @@
} }
table { table {
width: 100%; width: 100%;
table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
margin-top: 20px;
} }
th, td { th, td {
padding: 12px; padding: 12px;
text-align: left; text-align: center;
border-bottom: 1px solid #ddd; 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 { th {
background-color: #007bff; background-color: #007bff;
color: white; color: white;
font-weight: bold; font-weight: bold;
position: sticky;
top: 0;
} }
tr:hover { tr:hover {
background-color: #f1f1f1; background-color: #f1f1f1;
@@ -106,6 +120,7 @@
.add-row-btn:hover { .add-row-btn:hover {
background-color: #0056b3; background-color: #0056b3;
} }
</style> </style>
</head> </head>
<body> <body>
@@ -118,14 +133,25 @@
<div class="table-container"> <div class="table-container">
<button class="add-row-btn" id="add-row-one">Add Row</button> <button class="add-row-btn" id="add-row-one">Add Row</button>
<table id="table-one"> <table id="table-one">
<colgroup>
<col style="width: 5%"> <!-- # -->
<col style="width: 5%"> <!-- ID -->
<col style="width: 15%"> <!-- Client -->
<col style="width: 10%"> <!-- Druck -->
<col style="width: 10%"> <!-- Reinheit -->
<col style="width: 15%"> <!-- Date Joined -->
<col style="width: 25%"> <!-- Notes -->
<col style="width: 15%"> <!-- Actions -->
</colgroup>
<thead> <thead>
<tr> <tr>
<th>#</th> <th>#</th>
<th>ID</th> <th>ID</th>
<th>Client</th> <th>Client</th>
<th>Entry 1</th> <th>Druck</th>
<th>Entry 2</th> <th>Reinheit</th>
<th>Date Joined</th> <th>Date Joined</th>
<th>Notes</th>
<th>Actions</th> <th>Actions</th>
</tr> </tr>
</thead> </thead>
@@ -135,9 +161,10 @@
<td>{{ forloop.counter }}</td> <td>{{ forloop.counter }}</td>
<td>{{ entry.id }}</td> <td>{{ entry.id }}</td>
<td>{{ entry.client.name }}</td> <td>{{ entry.client.name }}</td>
<td>{{ entry.age }}</td> <td>{{ entry.pressure|floatformat:2 }}</td>
<td>{{ entry.email }}</td> <td>{{ entry.purity|floatformat:2 }}</td>
<td>{{ entry.date_joined }}</td> <td>{{ entry.date_joined|date:"Y-m-d" }}</td>
<td>{{ entry.notes|default:"" }}</td>
<td class="actions"> <td class="actions">
<button class="edit-btn-one">Edit</button> <button class="edit-btn-one">Edit</button>
<button class="delete-btn-one">Delete</button> <button class="delete-btn-one">Delete</button>
@@ -152,30 +179,72 @@
<!-- Add Popup --> <!-- Add Popup -->
<div id="add-popup-one" class="popup"> <div id="add-popup-one" class="popup">
<span class="close-btn">&times;</span> <span class="close-btn">&times;</span>
<h3>Add Entry</h3> <h3>He Gas Bundle</h3>
<label for="add-client-id">Kunde:</label>
<select id="add-client-id"> <select id="add-client-id">
{% for client in clients %} {% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option> <option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
<input type="number" id="add-age" placeholder="Age">
<input type="email" id="add-email" placeholder="Email"> <label for="add-date">Date:</label>
<button id="save-add-one">Add</button> <input type="date" id="add-date">
<div class="input-with-label">
<label for="add-pressure">Druck:</label>
<input type="number" id="add-pressure" placeholder="Enter pressure" step="0.01" min="0">
</div>
<div class="input-with-label">
<label for="add-purity">Reinheit:</label>
<input type="number" id="add-purity" placeholder="Enter purity" step="0.01" min="0" max="100">
</div>
<label for="add-notes">Notes:</label>
<textarea id="add-notes" placeholder="Additional notes"></textarea>
<div class="popup-buttons">
<button class="save-btn" id="save-add-one">Save</button>
<button class="cancel-btn">Cancel</button>
<button class="help-btn">Help</button>
</div>
</div> </div>
<!-- Edit Popup --> <!-- Edit Popup -->
<div id="edit-popup-one" class="popup"> <div id="edit-popup-one" class="popup">
<span class="close-btn">&times;</span> <span class="close-btn">&times;</span>
<h3>Edit Entry</h3> <h3>He Gas Bundle</h3>
<input type="hidden" id="edit-id"> <input type="hidden" id="edit-id">
<label for="edit-client-id">Kunde:</label>
<select id="edit-client-id"> <select id="edit-client-id">
{% for client in clients %} {% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option> <option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
<input type="number" id="edit-age" placeholder="Age">
<input type="email" id="edit-email" placeholder="Email"> <label for="edit-date">Date:</label>
<button id="save-edit-one">Save</button> <input type="date" id="edit-date">
<div class="input-with-label">
<label for="edit-pressure">Druck:</label>
<input type="number" id="edit-pressure" placeholder="Enter pressure" step="0.01" min="0">
</div>
<div class="input-with-label">
<label for="edit-purity">Reinheit:</label>
<input type="number" id="edit-purity" placeholder="Enter purity" step="0.01" min="0" max="100">
</div>
<label for="edit-notes">Notes:</label>
<textarea id="edit-notes" placeholder="Additional notes"></textarea>
<div class="popup-buttons">
<button class="save-btn" id="save-edit-one">Save</button>
<button class="cancel-btn">Cancel</button>
<button class="help-btn">Help</button>
</div>
</div> </div>
<script> <script>
@@ -192,81 +261,135 @@
}); });
// Add // Add
$('#save-add-one').on('click', function () { $('#save-add-one').on('click', function() {
let client_id = $('#add-client-id').val(); // Validate date first
let age = $('#add-age').val(); let dateInput = $('#add-date').val();
let email = $('#add-email').val(); if (!dateInput) {
alert('Please select a date');
return;
}
// Validate numbers
let pressure = parseFloat($('#add-pressure').val());
let purity = parseFloat($('#add-purity').val());
if (isNaN(pressure) || pressure < 0) {
alert('Please enter a valid pressure value');
return;
}
if (isNaN(purity) || purity < 0 || purity > 100) {
alert('Please enter a valid purity value (0-100)');
return;
}
// Prepare the form data
let formData = {
'client_id': $('#add-client-id').val(),
'date': dateInput,
'pressure': pressure,
'purity': purity,
'notes': $('#add-notes').val(),
'csrfmiddlewaretoken': '{{ csrf_token }}'
};
$.ajax({ $.ajax({
url: `/add-entry/${currentModelName}/`, url: '/add-entry/ExcelEntry/',
method: 'POST', method: 'POST',
data: { data: formData,
'client_id': client_id, success: function(response) {
'age': age, if (response.status === 'success') {
'email': email, // Add the new row to the table
'csrfmiddlewaretoken': '{{ csrf_token }}' let newRow = `
<tr data-id="${response.id}">
<td>${$('#table-one tbody tr').length + 1}</td>
<td>${response.id}</td>
<td>${response.client_name}</td>
<td>${response.pressure}</td>
<td>${response.purity}</td>
<td>${response.date || ''}</td>
<td>${response.notes || ''}</td>
<td class="actions">
<button class="edit-btn-one">Edit</button>
<button class="delete-btn-one">Delete</button>
</td>
</tr>
`;
$('#table-one tbody').append(newRow);
$('#add-popup-one').fadeOut();
} else {
alert('Error: ' + (response.message || 'Failed to add entry'));
}
}, },
success: function (response) { error: function(xhr) {
let rowCount = $(`#${currentTableId} tbody tr`).length + 1; alert('Error: ' + (xhr.responseJSON?.message || 'Server error'));
let newRow = `
<tr data-id="${response.id}">
<td>${rowCount}</td>
<td>${response.id}</td>
<td>${response.client_name}</td>
<td>${response.age}</td>
<td>${response.email}</td>
<td>${response.date_joined}</td>
<td class="actions">
<button class="edit-btn-one">Edit</button>
<button class="delete-btn-one">Delete</button>
</td>
</tr>
`;
$(`#${currentTableId} tbody`).append(newRow);
$('#add-popup-one').fadeOut();
} }
}); });
}); });
// Edit // Edit
$(document).on('click', '.edit-btn-one', function () { $(document).on('click', '.edit-btn-one', function() {
let row = $(this).closest('tr'); let row = $(this).closest('tr');
$('#edit-id').val(row.data('id')); $('#edit-id').val(row.data('id'));
$('#edit-client-id').val(row.find('td:eq(2)').text()); $('#edit-client-id').val(row.find('td:eq(2)').text().trim());
$('#edit-age').val(row.find('td:eq(3)').text());
$('#edit-email').val(row.find('td:eq(4)').text()); // Handle date - ensure it's in correct format
let dateText = row.find('td:eq(5)').text().trim();
if (dateText) {
$('#edit-date').val(dateText);
}
$('#edit-pressure').val(row.find('td:eq(3)').text().trim());
$('#edit-purity').val(row.find('td:eq(4)').text().trim());
$('#edit-notes').val(row.find('td:eq(6)').text().trim());
$('#edit-popup-one').fadeIn(); $('#edit-popup-one').fadeIn();
}); });
$('#save-edit-one').on('click', function () { // Update the save-edit-one handler
let id = $('#edit-id').val(); $('#save-edit-one').on('click', function() {
let client_id = $('#edit-client-id').val(); let formData = {
let age = $('#edit-age').val(); 'id': $('#edit-id').val(),
let email = $('#edit-email').val(); 'client_id': $('#edit-client-id').val(),
'date': $('#edit-date').val(), // Already in YYYY-MM-DD format
'pressure': $('#edit-pressure').val(),
'purity': $('#edit-purity').val(),
'notes': $('#edit-notes').val(),
'csrfmiddlewaretoken': '{{ csrf_token }}'
};
// Validate inputs
if (!formData.date) {
alert('Please select a date');
return;
}
if (isNaN(formData.pressure) || formData.pressure < 0) {
alert('Please enter a valid pressure value');
return;
}
if (isNaN(formData.purity) || formData.purity < 0 || formData.purity > 100) {
alert('Please enter a valid purity value (0-100)');
return;
}
$.ajax({ $.ajax({
url: `/update-entry/${currentModelName}/`, url: '/update-entry/ExcelEntry/',
method: 'POST', method: 'POST',
data: { data: formData,
'id': id, success: function(response) {
'client_id': client_id,
'age': age,
'email': email,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (response) {
if (response.status === 'success') { if (response.status === 'success') {
let row = $(`tr[data-id="${response.id}"]`); let row = $(`tr[data-id="${response.id}"]`);
row.find('td:eq(2)').text(response.name); row.find('td:eq(2)').text(response.client_name);
row.find('td:eq(3)').text(response.age); row.find('td:eq(3)').text(response.pressure);
row.find('td:eq(4)').text(response.email); row.find('td:eq(4)').text(response.purity);
row.find('td:eq(5)').text(response.date || '');
row.find('td:eq(6)').text(response.notes || '');
$('#edit-popup-one').fadeOut(); $('#edit-popup-one').fadeOut();
} else { } else {
alert('Failed to update entry: ' + response.message); alert('Error: ' + (response.message || 'Failed to update entry'));
} }
}, },
error: function () { error: function(xhr) {
alert('Failed to update entry. Please try again.'); alert('Error: ' + (xhr.responseJSON?.message || 'Server error'));
} }
}); });
}); });

View File

@@ -1,14 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"/> <meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Helium Output</title> <title>Helium Output</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" rel="stylesheet"/> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
<style> <style>
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 0; margin: 0;
@@ -76,23 +75,56 @@
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000; z-index: 1000;
width: 400px;
} }
.popup input { .popup h3 {
margin-top: 0;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.popup label {
display: block; display: block;
margin-bottom: 10px; margin-bottom: 5px;
font-weight: bold;
}
.popup input, .popup select, .popup textarea {
display: block;
margin-bottom: 15px;
width: 100%; width: 100%;
padding: 8px; padding: 8px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
box-sizing: border-box;
}
.popup textarea {
height: 100px;
resize: vertical;
}
.popup-buttons {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
} }
.popup button { .popup button {
margin-top: 10px;
padding: 8px 16px; padding: 8px 16px;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
} }
.save-btn {
background-color: #28a745;
color: white;
}
.cancel-btn {
background-color: #6c757d;
color: white;
}
.help-btn {
background-color: #17a2b8;
color: white;
}
.close-btn { .close-btn {
cursor: pointer; cursor: pointer;
float: right; float: right;
@@ -112,174 +144,244 @@
.add-row-btn:hover { .add-row-btn:hover {
background-color: #0056b3; background-color: #0056b3;
} }
.popup select { .checkbox-container {
display: block; display: flex;
margin-bottom: 10px; align-items: center;
width: 100%; margin-bottom: 15px;
padding: 8px; }
border: 1px solid #ddd; .checkbox-container input[type="checkbox"] {
border-radius: 4px; width: auto;
font-family: Arial, sans-serif; margin-right: 10px;
margin-bottom: 0;
}
.input-with-label {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.input-with-label label {
width: 120px;
margin-bottom: 0;
margin-right: 10px;
}
.input-with-label input {
flex: 1;
margin-bottom: 0;
} }
</style> </style>
</head> </head>
<body> <body>
<div class="d-flex justify-content-start mb-2">
<!-- "Go to Clients" button at top-left --> <div class="d-flex justify-content-start mb-2">
<a class="btn btn-outline-primary" href="{% url 'clients_list' %}"> <!-- "Go to Clients" button at top-left -->
⇦ Go to Clients <a href="{% url 'clients_list' %}" class="btn btn-outline-primary">
&#8678; Go to Clients
</a> </a>
</div>
<h2>Helium Output</h2>
<!-- Second Table -->
<div class="table-container">
<button class="add-row-btn" id="add-row-two">Add Row</button>
<table id="table-two">
<thead><tr><th>#</th><th>ID</th><th>Client</th><th>Date</th><th>Warm</th><th>LHe Anlieferung</th><th>LHe Ausgabe</th><th>Comments</th><th>Actions</th></tr></thead>
<tbody>
{% for entry in entries_table2 %}
<tr data-id="{{ entry.id }}">
<td>{{ forloop.counter }}</td>
<td>{{ entry.id }}</td>
<td>{{ entry.client.name }}</td>
<td>{{ entry.age }}</td>
<td>{{ entry.email }}</td>
<td>{{ entry.date_joined }}</td>
<td class="actions">
<button class="edit-btn-two">Edit</button>
<button class="delete-btn-two">Delete</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Add Entry Popup -->
<div id="add-popup-two" class="popup" style="display:none;">
<span class="close-btn">&times;</span>
<h3>Add Entry</h3>
<label for="add-client-id">Kunde:</label>
<select id="add-client-id">
{% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %}
</select>
<label for="add-date">Datum:</label>
<input type="date" id="add-date">
<label><input type="checkbox" id="add-warm"> warm</label>
<label for="add-lhe-anlieferung">LHe Anlieferung:</label>
<input type="text" id="add-lhe-anlieferung" placeholder="LHe Anlieferung">
<label for="add-lhe-ausgabe">LHe Ausgabe:</label>
<input type="text" id="add-lhe-ausgabe" placeholder="LHe Ausgabe">
<label for="add-comment">Kommentar:</label>
<textarea id="add-comment" rows="4"></textarea>
<div style="margin-top: 10px;">
<button id="save-add-two">💾 Save</button>
<button class="close-btn">❌ Cancel</button>
<button id="help-btn">❓ Help</button>
</div> </div>
</div>
</div> <h2>LHe Dewar Output</h2>
<!-- Edit Entry Popup -->
<div class="popup" id="edit-popup-two">
<span class="close-btn">×</span>
<h3>Edit Entry</h3>
<input id="edit-id" type="hidden"/>
<label for="edit-client-id">Kunde:</label>
<select id="edit-client-id">
{% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %}
</select>
<label><input id="edit-warm" type="checkbox"/> warm</label>
<input id="edit-anlieferung" placeholder="LHe Anlieferung" type="text"/>
<input id="edit-ausgabe" placeholder="LHe Ausgabe" type="text"/>
<textarea id="edit-comments" placeholder="Comments" rows="4"></textarea>
<button id="save-edit-two">Save</button>
<button class="close-btn">Cancel</button>
<button id="help-btn-edit-two">Help</button>
</div>
<script>
$(document).ready(function () {
let currentTableId = null; // To track which table is being edited
let currentModelName = null; // To track which model is being used
// Open Add Popup for Table 2 <div class="table-container">
$('#add-row-two').on('click', function () { <button class="add-row-btn" id="add-row-two">Add Output</button>
currentTableId = 'table-two'; <table id="table-two">
currentModelName = 'SecondTableEntry'; // Model name for Table 2 <thead>
$('#add-popup-two').fadeIn(); <tr>
}); <th>#</th>
<th>ID</th>
// Close Popups <th>Client</th>
$('.close-btn').on('click', function () { <th>Date</th>
$('.popup').fadeOut(); <th>Warm</th>
}); <th>LHe Delivery</th>
<th>LHe Output</th>
// Save Add Entry <th>Notes</th>
$('#save-add-two').on('click', function () { <th>Actions</th>
let client_id = $('#add-client-id').val(); </tr>
let date = $('#add-date').val(); </thead>
let warm = $('#add-warm').is(':checked') ? 1 : 0; <tbody>
let lhe_anlieferung = $('#add-lhe-anlieferung').val(); {% for entry in entries_table2 %}
let lhe_ausgabe = $('#add-lhe-ausgabe').val(); <tr data-id="{{ entry.id }}">
let comment = $('#add-comment').val(); <td>{{ forloop.counter }}</td>
<td>{{ entry.id }}</td>
$.ajax({ <td>{{ entry.client.name }}</td>
url: '/add-entry/SecondTableEntry/', <td>{{ entry.date }}</td>
method: 'POST', <td>{{ entry.is_warm|yesno:"Yes,No" }}</td>
data: { <td>{{ entry.lhe_delivery }}</td>
'client_id': client_id, <td>{{ entry.lhe_output }}</td>
'date': date, <td>{{ entry.notes }}</td>
'warm': warm,
'lhe_anlieferung': lhe_anlieferung,
'lhe_ausgabe': lhe_ausgabe,
'comment': comment,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function (response) {
let rowCount = $('tbody tr').length + 1;
let newRow = `
<tr data-id="${response.id}">
<td>${rowCount}</td>
<td>${response.id}</td>
<td>${response.name}</td>
<td>${response.warm}</td>
<td>${response.lhe_anlieferung}</td>
<td>${response.lhe_ausgabe}</td>
<td>${response.date}</td>
<td class="actions"> <td class="actions">
<button class="edit-btn-two">Edit</button> <button class="edit-btn-two">Edit</button>
<button class="delete-btn-two">Delete</button> <button class="delete-btn-two">Delete</button>
</td> </td>
</tr>`; </tr>
$('tbody').append(newRow); {% endfor %}
$('#add-popup-two').fadeOut(); </tbody>
}, </table>
error: function (xhr) { </div>
alert('Failed to add entry: ' + xhr.responseText);
} <!-- Add Entry Popup -->
}); <div id="add-popup-two" class="popup">
}); <span class="close-btn">&times;</span>
<h3>LHe Dewar Output</h3>
<label for="add-client-id">Client:</label>
<select id="add-client-id">
{% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %}
</select>
<label for="add-date">Date:</label>
<input type="date" id="add-date">
<div class="checkbox-container">
<input type="checkbox" id="add-is-warm">
<label for="add-is-warm">Warm</label>
</div>
<div class="input-with-label">
<label for="add-lhe-delivery">LHe Anlieferung:</label>
<input type="text" id="add-lhe-delivery" placeholder="Enter delivery amount">
</div>
<div class="input-with-label">
<label for="add-lhe-output">LHe Ausgabe:</label>
<input type="number" id="add-lhe-output" placeholder="Enter output amount (numbers only)" step="0.01" min="0" placeholder="Enter output amount">
</div>
<label for="add-notes">Notes:</label>
<textarea id="add-notes" placeholder="Additional notes"></textarea>
<div class="popup-buttons">
<button class="save-btn" id="save-add-two">Save</button>
<button class="cancel-btn" id="cancel-add-two">Cancel</button>
<button class="help-btn">Help</button>
</div>
</div>
<!-- Edit Entry Popup -->
<div id="edit-popup-two" class="popup">
<span class="close-btn">&times;</span>
<h3>LHe Dewar Output</h3>
<input type="hidden" id="edit-id">
<label for="edit-client-id">Client:</label>
<select id="edit-client-id">
{% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %}
</select>
<label for="edit-date">Date:</label>
<input type="date" id="edit-date">
<div class="checkbox-container">
<input type="checkbox" id="edit-is-warm">
<label for="edit-is-warm">Warm</label>
</div>
<div class="input-with-label">
<label for="edit-lhe-delivery">LHe Anlieferung:</label>
<input type="text" id="edit-lhe-delivery" placeholder="Enter delivery amount">
</div>
<div class="input-with-label">
<label for="edit-lhe-output">LHe Ausgabe:</label>
<input type="number" id="edit-lhe-output" placeholder="Enter output amount">
</div>
<label for="edit-notes">Notes:</label>
<textarea id="edit-notes" placeholder="Additional notes"></textarea>
<div class="popup-buttons">
<button class="save-btn" id="save-edit-two">Save</button>
<button class="cancel-btn" id="cancel-edit-two">Cancel</button>
<button class="help-btn">Help</button>
</div>
</div>
<script>
$(document).ready(function () {
let currentTableId = null;
let currentModelName = null;
// Open Add Popup for Table 2
$('#add-row-two').on('click', function () {
currentTableId = 'table-two';
currentModelName = 'SecondTableEntry';
$('#add-popup-two').fadeIn();
}); });
// Close Popups
$('.close-btn, .cancel-btn').on('click', function () {
$('.popup').fadeOut();
});
// Save Add Entry
$('#save-add-two').on('click', function() {
let formData = {
'client_id': $('#add-client-id').val(),
'date': $('#add-date').val(),
'is_warm': $('#add-is-warm').is(':checked'),
'lhe_delivery': $('#add-lhe-delivery').val(),
'lhe_output': $('#add-lhe-output').val(),
'notes': $('#add-notes').val(),
'csrfmiddlewaretoken': '{{ csrf_token }}'
};
// Validate LHe Output is a number
if (isNaN(parseFloat(formData.lhe_output))) {
alert('LHe Output must be a valid number');
return;
}
$.ajax({
url: '/add-entry/SecondTableEntry/',
method: 'POST',
data: formData,
success: function(response) {
// Clear the form
$('#add-popup-two').find('input, textarea, select').val('');
$('#add-is-warm').prop('checked', false);
$('#add-popup-two').fadeOut();
// Reload the table data
loadTableData();
},
error: function(xhr) {
alert('Error: ' + xhr.responseJSON?.message || 'Failed to add entry');
}
});
});
// Add this new function to load table data
function loadTableData() {
$.ajax({
url: window.location.href,
method: 'GET',
success: function(data) {
// Parse the HTML response to extract the table body
let newBody = $(data).find('#table-two tbody').html();
$('#table-two tbody').html(newBody);
},
error: function() {
alert('Failed to refresh table data');
}
});
}
// Open Edit Popup // Open Edit Popup
$(document).on('click', '.edit-btn-two', function () { $(document).on('click', '.edit-btn-two', function () {
let row = $(this).closest('tr'); let row = $(this).closest('tr');
currentTableId = row.closest('table').attr('id'); // Set current table ID currentTableId = row.closest('table').attr('id');
currentModelName = 'SecondTableEntry'; // Set model name currentModelName = 'SecondTableEntry';
// Get data from the row
let is_warm = row.find('td:eq(4)').text().trim() === 'Yes';
$('#edit-id').val(row.data('id')); $('#edit-id').val(row.data('id'));
$('#edit-client-id').val(row.find('td:eq(2)').text()); // Name is now in column 2 $('#edit-client-id').val(row.find('td:eq(2)').text().trim());
$('#edit-age').val(row.find('td:eq(3)').text()); // Age is now in column 3 $('#edit-date').val(row.find('td:eq(3)').text().trim());
$('#edit-email').val(row.find('td:eq(4)').text()); // Email is now in column 4 $('#edit-is-warm').prop('checked', is_warm);
$('#edit-lhe-delivery').val(row.find('td:eq(5)').text().trim());
$('#edit-lhe-output').val(row.find('td:eq(6)').text().trim());
$('#edit-notes').val(row.find('td:eq(7)').text().trim());
$('#edit-popup-two').fadeIn(); $('#edit-popup-two').fadeIn();
}); });
@@ -287,8 +389,11 @@ $('#save-add-two').on('click', function () {
$('#save-edit-two').on('click', function () { $('#save-edit-two').on('click', function () {
let id = $('#edit-id').val(); let id = $('#edit-id').val();
let client_id = $('#edit-client-id').val(); let client_id = $('#edit-client-id').val();
let age = $('#edit-age').val(); let date = $('#edit-date').val();
let email = $('#edit-email').val(); let is_warm = $('#edit-is-warm').is(':checked');
let lhe_delivery = $('#edit-lhe-delivery').val();
let lhe_output = $('#edit-lhe-output').val();
let notes = $('#edit-notes').val();
$.ajax({ $.ajax({
url: `/update-entry/${currentModelName}/`, url: `/update-entry/${currentModelName}/`,
@@ -296,23 +401,30 @@ $('#save-add-two').on('click', function () {
data: { data: {
'id': id, 'id': id,
'client_id': client_id, 'client_id': client_id,
'age': age, 'date': date,
'email': email, 'is_warm': is_warm,
'lhe_delivery': lhe_delivery,
'lhe_output': lhe_output,
'notes': notes,
'csrfmiddlewaretoken': '{{ csrf_token }}' 'csrfmiddlewaretoken': '{{ csrf_token }}'
}, },
success: function (response) { success: function (response) {
if (response.status === 'success') { if (response.status === 'success') {
let row = $(`tr[data-id="${response.id}"]`); let row = $(`tr[data-id="${response.id}"]`);
row.find('td:eq(2)').text(response.name); row.find('td:eq(2)').text(response.client_name);
row.find('td:eq(3)').text(response.age); row.find('td:eq(3)').text(response.date);
row.find('td:eq(4)').text(response.email); row.find('td:eq(4)').text(response.is_warm ? 'Yes' : 'No');
row.find('td:eq(5)').text(response.lhe_delivery);
row.find('td:eq(6)').text(response.lhe_output);
row.find('td:eq(7)').text(response.notes);
$('#edit-popup-two').fadeOut(); $('#edit-popup-two').fadeOut();
} else { } else {
alert('Failed to update entry: ' + response.message); alert('Update failed: ' + (response.message || 'Please try again later'));
} }
}, },
error: function () { error: function (xhr, status, error) {
alert('Failed to update entry. Please try again.'); alert('Update failed: ' + (xhr.responseJSON?.message || 'Please try again later'));
console.error('Error:', error);
} }
}); });
}); });
@@ -321,8 +433,8 @@ $('#save-add-two').on('click', function () {
$(document).on('click', '.delete-btn-two', function () { $(document).on('click', '.delete-btn-two', function () {
let row = $(this).closest('tr'); let row = $(this).closest('tr');
let id = row.data('id'); let id = row.data('id');
currentTableId = row.closest('table').attr('id'); // Set current table ID currentTableId = row.closest('table').attr('id');
currentModelName = 'SecondTableEntry'; // Set model name currentModelName = 'SecondTableEntry';
if (!confirm('Are you sure you want to delete this entry?')) return; if (!confirm('Are you sure you want to delete this entry?')) return;
@@ -337,11 +449,12 @@ $('#save-add-two').on('click', function () {
if (response.status === 'success') { if (response.status === 'success') {
row.fadeOut(300, function () { $(this).remove(); }); row.fadeOut(300, function () { $(this).remove(); });
} else { } else {
alert('Failed to delete entry: ' + response.message); alert('Delete failed: ' + response.message);
} }
}, },
error: function () { error: function (xhr, status, error) {
alert('Failed to delete entry. Please try again.'); alert('Delete failed: ' + (xhr.responseJSON?.message || 'Please try again later'));
console.error('Error:', error);
} }
}); });
}); });

View File

@@ -1,20 +1,51 @@
from django.shortcuts import render from django.shortcuts import render
from django.http import JsonResponse from django.http import JsonResponse
from django.db.models import Q
from decimal import Decimal, InvalidOperation
from django.apps import apps from django.apps import apps
from datetime import date from datetime import date, datetime
from .models import Client from django.utils import timezone
from .models import Client, SecondTableEntry
from django.db.models import Sum
# Clients Page (Main) # Clients Page (Main)
def clients_list(request): def clients_list(request):
clients = Client.objects.all().order_by('id') # Annual summary data
return render(request, 'clients_table.html', {'clients': clients}) current_year = int(request.GET.get('year', datetime.now().year))
clients = Client.objects.all()
monthly_data = []
for client in clients:
monthly_totals = []
for month in range(1, 13):
total = SecondTableEntry.objects.filter(
client=client,
date__year=current_year,
date__month=month
).aggregate(total=Sum('lhe_output'))['total'] or 0
monthly_totals.append(total)
monthly_data.append({
'client': client,
'monthly_totals': monthly_totals,
'year_total': sum(monthly_totals)
})
available_years = SecondTableEntry.objects.dates('date', 'year').distinct()
return render(request, 'clients_table.html', {
'monthly_data': monthly_data,
'current_year': current_year,
'available_years': [y.year for y in available_years],
'months': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
})
# Table One View (ExcelEntry) # Table One View (ExcelEntry)
def table_one_view(request): def table_one_view(request):
ExcelEntry = apps.get_model('sheets', 'ExcelEntry') ExcelEntry = apps.get_model('sheets', 'ExcelEntry')
entries_table1 = ExcelEntry.objects.all() entries_table1 = ExcelEntry.objects.all().select_related('client')
clients = Client.objects.all() clients = Client.objects.all()
return render(request, 'table_one.html', { return render(request, 'table_one.html', {
'entries_table1': entries_table1, 'entries_table1': entries_table1,
@@ -24,13 +55,23 @@ def table_one_view(request):
# Table Two View (SecondTableEntry) # Table Two View (SecondTableEntry)
def table_two_view(request): def table_two_view(request):
SecondTableEntry = apps.get_model('sheets', 'SecondTableEntry') try:
entries_table2 = SecondTableEntry.objects.all() SecondTableEntry = apps.get_model('sheets', 'SecondTableEntry')
clients = Client.objects.all() entries = SecondTableEntry.objects.all().order_by('-date')
return render(request, 'table_two.html', { clients = Client.objects.all()
'entries_table2': entries_table2,
'clients': clients, return render(request, 'table_two.html', {
}) 'entries_table2': entries,
'clients': clients,
})
except Exception as e:
return render(request, 'table_two.html', {
'error_message': f"Failed to load data: {str(e)}",
'entries_table2': [],
'clients': Client.objects.all()
})
# Add Entry (Generic) # Add Entry (Generic)
@@ -38,43 +79,75 @@ def add_entry(request, model_name):
if request.method == 'POST': if request.method == 'POST':
try: try:
model = apps.get_model('sheets', model_name) model = apps.get_model('sheets', model_name)
common_data = {
'client': Client.objects.get(id=request.POST.get('client_id')),
'date': request.POST.get('date'),
'notes': request.POST.get('notes', '')
}
if model_name == 'SecondTableEntry':
# Handle Helium Output (Table Two)
lhe_output = request.POST.get('lhe_output')
entry = model.objects.create(
**common_data,
is_warm=request.POST.get('is_warm') == 'true',
lhe_delivery=request.POST.get('lhe_delivery', ''),
lhe_output=Decimal(lhe_output) if lhe_output else None
)
if model_name.lower() == 'client':
name = request.POST.get('name', 'New Name')
address = request.POST.get('address', '')
entry = model.objects.create(name=name, address=address)
return JsonResponse({ return JsonResponse({
'status': 'success',
'id': entry.id, 'id': entry.id,
'name': entry.name, 'client_name': entry.client.name,
'address': entry.address, 'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
'is_warm': entry.is_warm,
'lhe_delivery': entry.lhe_delivery,
'lhe_output': str(entry.lhe_output) if entry.lhe_output else '',
'notes': entry.notes
}) })
client_id = request.POST.get('client_id') elif model_name == 'ExcelEntry':
client = Client.objects.get(id=client_id) # Parse the date string into a date object
age = int(request.POST.get('age', 0)) date_str = request.POST.get('date')
email = request.POST.get('email', 'example@email.com') try:
date_obj = datetime.strptime(date_str, '%Y-%m-%d').date() if date_str else None
except (ValueError, TypeError):
date_obj = None
# Create the entry
entry = model.objects.create(
client=Client.objects.get(id=request.POST.get('client_id')),
date=date_obj,
pressure=Decimal(request.POST.get('pressure', 0)),
purity=Decimal(request.POST.get('purity', 0)),
notes=request.POST.get('notes', '')
)
entry = model.objects.create( # Prepare the response
client=client, response_data = {
age=age, 'status': 'success',
email=email, 'id': entry.id,
date_joined=date.today() 'client_name': entry.client.name,
) 'pressure': str(entry.pressure),
'purity': str(entry.purity),
'notes': entry.notes
}
# Only add date if it exists
if entry.date:
response_data['date'] = entry.date.strftime('%Y-%m-%d')
else:
response_data['date'] = None
return JsonResponse(response_data)
return JsonResponse({ # Keep your existing SecondTableEntry code here...
'id': entry.id,
'client_name': client.name,
'age': entry.age,
'email': entry.email,
'date_joined': entry.date_joined.strftime('%Y-%m-%d'),
})
except Exception as e: except Exception as e:
return JsonResponse({'status': 'error', 'message': str(e)}, status=400) return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400) return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
# Update Entry (Generic) # Update Entry (Generic)
def update_entry(request, model_name): def update_entry(request, model_name):
if request.method == 'POST': if request.method == 'POST':
@@ -83,44 +156,60 @@ def update_entry(request, model_name):
entry_id = int(request.POST.get('id')) entry_id = int(request.POST.get('id'))
entry = model.objects.get(id=entry_id) entry = model.objects.get(id=entry_id)
if model_name.lower() == 'client': # Common updates for both models
entry.name = request.POST.get('name') entry.client = Client.objects.get(id=request.POST.get('client_id'))
entry.address = request.POST.get('address', '') entry.date = request.POST.get('date')
entry.notes = request.POST.get('notes', '')
if model_name == 'SecondTableEntry':
# Handle Helium Output (Table Two)
lhe_output = request.POST.get('lhe_output')
entry.is_warm = request.POST.get('is_warm') == 'true'
entry.lhe_delivery = request.POST.get('lhe_delivery', '')
entry.lhe_output = Decimal(lhe_output) if lhe_output else None
entry.save() entry.save()
return JsonResponse({ return JsonResponse({
'status': 'success', 'status': 'success',
'id': entry.id, 'id': entry.id,
'name': entry.name, 'client_name': entry.client.name,
'address': entry.address, 'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
'is_warm': entry.is_warm,
'lhe_delivery': entry.lhe_delivery,
'lhe_output': str(entry.lhe_output) if entry.lhe_output else '',
'notes': entry.notes
}) })
client_id = request.POST.get('client_id') elif model_name == 'ExcelEntry':
client = Client.objects.get(id=client_id) # Handle Helium Input (Table One)
age = int(request.POST.get('age')) date_str = request.POST.get('date')
email = request.POST.get('email') try:
date_obj = datetime.strptime(date_str, '%Y-%m-%d').date() if date_str else None
except (ValueError, TypeError):
date_obj = None
entry.client = client entry.client = Client.objects.get(id=request.POST.get('client_id'))
entry.age = age entry.date = date_obj
entry.email = email entry.pressure = Decimal(request.POST.get('pressure', 0))
entry.save() entry.purity = Decimal(request.POST.get('purity', 0))
entry.notes = request.POST.get('notes', '')
return JsonResponse({ entry.save()
'status': 'success',
'id': entry.id,
'name': client.name,
'age': entry.age,
'email': entry.email,
'date_joined': entry.date_joined.strftime('%Y-%m-%d'),
})
return JsonResponse({
'status': 'success',
'id': entry.id,
'client_name': entry.client.name,
'pressure': str(entry.pressure),
'purity': str(entry.purity),
'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
'notes': entry.notes
})
except model.DoesNotExist: except model.DoesNotExist:
return JsonResponse({'status': 'error', 'message': 'Entry not found'}, status=404) return JsonResponse({'status': 'error', 'message': 'Entry not found'}, status=404)
except Exception as e: except Exception as e:
return JsonResponse({'status': 'error', 'message': str(e)}, status=400) return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400) return JsonResponse({'status': 'error', 'message': 'Invalid request method'}, status=400)
# Delete Entry (Generic) # Delete Entry (Generic)
def delete_entry(request, model_name): def delete_entry(request, model_name):
if request.method == 'POST': if request.method == 'POST':
@@ -136,4 +225,4 @@ def delete_entry(request, model_name):
except Exception as e: except Exception as e:
return JsonResponse({'status': 'error', 'message': str(e)}, status=400) return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400) return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)