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; {% block content %}
color: white; <div class="container">
} <!-- Year Filter -->
.delete-btn { <div class="year-filter">
background-color: #dc3545; <label for="year-select">Year:</label>
color: white; <select id="year-select" onchange="window.location.href='?year='+this.value">
} {% for year in available_years %}
.popup { <option value="{{ year }}" {% if year == current_year %}selected{% endif %}>
display: none; {{ year }}
position: fixed; </option>
top: 50%; {% endfor %}
left: 50%; </select>
transform: translate(-50%, -50%); </div>
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>
<!-- Annual Summary Table -->
<div class="container"> <table class="summary-table">
<h2>Clients Table</h2>
<button class="add-row-btn" id="add-client">Add Client</button>
<table>
<thead> <thead>
<tr> <tr>
<th>#</th> <!-- This is your new sequential number column --> <th>Client</th>
<th>ID</th> {% for month in months %}
<th>Name</th> <th>{{ month }}</th>
<th>Address</th> {% endfor %}
<th>Actions</th> <th>Total</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for client in clients %} {% for data in monthly_data %}
<tr data-id="{{ client.id }}"> <tr>
<td>{{ forloop.counter }}</td> <!-- ← this gives you 1, 2, 3... --> <td>{{ data.client.name }}</td>
<td>{{ client.id }}</td> {% for total in data.monthly_totals %}
<td>{{ client.name }}</td> <td>{{ total|floatformat:2 }}</td>
<td>{{ client.address }}</td> {% endfor %}
<td class="actions"> <td class="total">{{ data.year_total|floatformat:2 }}</td>
<button class="edit-btn">Edit</button>
<button class="delete-btn">Delete</button>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div>
<!-- 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>
<script> .container {
let currentModelName = "Client"; max-width: 1200px;
margin: 0 auto;
// Open Add Popup padding: 20px;
$('#add-client').on('click', function () {
$('#add-popup').fadeIn();
});
// Close Popups
$('.close-btn').on('click', function () {
$('.popup').fadeOut();
});
// Save Add Client
$('#save-add').on('click', function () {
let name = $('#add-name').val();
let address = $('#add-address').val();
$.ajax({
url: `/add-entry/Client/`,
method: 'POST',
data: {
'name': name,
'address': address,
'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 .year-filter {
$(document).on('click', '.edit-btn', function () { margin: 20px 0;
let row = $(this).closest('tr'); text-align: right;
$('#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();
} }
.year-filter label {
margin-right: 10px;
} }
});
});
// Delete Client .year-filter select {
$(document).on('click', '.delete-btn', function () { padding: 5px;
let row = $(this).closest('tr'); border-radius: 4px;
let id = row.data('id'); border: 1px solid #ddd;
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> .summary-table {
</html> 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;
}
.navigation-buttons {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 30px;
}
.nav-button {
padding: 12px 24px;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 4px;
transition: background-color 0.3s;
}
.nav-button:hover {
background-color: #0056b3;
}
</style>
{% endblock %}

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 }}'
},
success: function (response) {
let rowCount = $(`#${currentTableId} tbody tr`).length + 1;
let newRow = ` let newRow = `
<tr data-id="${response.id}"> <tr data-id="${response.id}">
<td>${rowCount}</td> <td>${$('#table-one tbody tr').length + 1}</td>
<td>${response.id}</td> <td>${response.id}</td>
<td>${response.client_name}</td> <td>${response.client_name}</td>
<td>${response.age}</td> <td>${response.pressure}</td>
<td>${response.email}</td> <td>${response.purity}</td>
<td>${response.date_joined}</td> <td>${response.date || ''}</td>
<td>${response.notes || ''}</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>
</td> </td>
</tr> </tr>
`; `;
$(`#${currentTableId} tbody`).append(newRow); $('#table-one tbody').append(newRow);
$('#add-popup-one').fadeOut(); $('#add-popup-one').fadeOut();
} else {
alert('Error: ' + (response.message || 'Failed to add entry'));
}
},
error: function(xhr) {
alert('Error: ' + (xhr.responseJSON?.message || 'Server error'));
} }
}); });
}); });
// 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> </div>
<h2>Helium Output</h2>
<!-- Second Table --> <h2>LHe Dewar Output</h2>
<div class="table-container">
<button class="add-row-btn" id="add-row-two">Add Row</button> <div class="table-container">
<table id="table-two"> <button class="add-row-btn" id="add-row-two">Add Output</button>
<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> <table id="table-two">
<tbody> <thead>
<tr>
<th>#</th>
<th>ID</th>
<th>Client</th>
<th>Date</th>
<th>Warm</th>
<th>LHe Delivery</th>
<th>LHe Output</th>
<th>Notes</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for entry in entries_table2 %} {% for entry in entries_table2 %}
<tr data-id="{{ entry.id }}"> <tr data-id="{{ entry.id }}">
<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.date }}</td>
<td>{{ entry.email }}</td> <td>{{ entry.is_warm|yesno:"Yes,No" }}</td>
<td>{{ entry.date_joined }}</td> <td>{{ entry.lhe_delivery }}</td>
<td class="actions"> <td>{{ entry.lhe_output }}</td>
<button class="edit-btn-two">Edit</button> <td>{{ entry.notes }}</td>
<button class="delete-btn-two">Delete</button> <td class="actions">
</td> <button class="edit-btn-two">Edit</button>
</tr> <button class="delete-btn-two">Delete</button>
</td>
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<!-- Add Entry Popup --> <!-- Add Entry Popup -->
<div id="add-popup-two" class="popup" style="display:none;"> <div id="add-popup-two" class="popup">
<span class="close-btn">&times;</span> <span class="close-btn">&times;</span>
<h3>Add Entry</h3> <h3>LHe Dewar Output</h3>
<label for="add-client-id">Kunde:</label> <label for="add-client-id">Client:</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>
<label for="add-date">Date:</label>
<label for="add-date">Datum:</label>
<input type="date" id="add-date"> <input type="date" id="add-date">
<label><input type="checkbox" id="add-warm"> warm</label> <div class="checkbox-container">
<input type="checkbox" id="add-is-warm">
<label for="add-lhe-anlieferung">LHe Anlieferung:</label> <label for="add-is-warm">Warm</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> <div class="input-with-label">
<!-- Edit Entry Popup --> <label for="add-lhe-delivery">LHe Anlieferung:</label>
<div class="popup" id="edit-popup-two"> <input type="text" id="add-lhe-delivery" placeholder="Enter delivery amount">
<span class="close-btn">×</span> </div>
<h3>Edit Entry</h3>
<input id="edit-id" type="hidden"/> <div class="input-with-label">
<label for="edit-client-id">Kunde:</label> <label for="add-lhe-output">LHe Ausgabe:</label>
<select id="edit-client-id"> <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 %} {% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option> <option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
<label><input id="edit-warm" type="checkbox"/> warm</label> <label for="edit-date">Date:</label>
<input id="edit-anlieferung" placeholder="LHe Anlieferung" type="text"/> <input type="date" id="edit-date">
<input id="edit-ausgabe" placeholder="LHe Ausgabe" type="text"/>
<textarea id="edit-comments" placeholder="Comments" rows="4"></textarea> <div class="checkbox-container">
<button id="save-edit-two">Save</button> <input type="checkbox" id="edit-is-warm">
<button class="close-btn">Cancel</button> <label for="edit-is-warm">Warm</label>
<button id="help-btn-edit-two">Help</button> </div>
</div>
<script> <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 () { $(document).ready(function () {
let currentTableId = null; // To track which table is being edited let currentTableId = null;
let currentModelName = null; // To track which model is being used let currentModelName = null;
// Open Add Popup for Table 2 // Open Add Popup for Table 2
$('#add-row-two').on('click', function () { $('#add-row-two').on('click', function () {
currentTableId = 'table-two'; currentTableId = 'table-two';
currentModelName = 'SecondTableEntry'; // Model name for Table 2 currentModelName = 'SecondTableEntry';
$('#add-popup-two').fadeIn(); $('#add-popup-two').fadeIn();
}); });
// Close Popups // Close Popups
$('.close-btn').on('click', function () { $('.close-btn, .cancel-btn').on('click', function () {
$('.popup').fadeOut(); $('.popup').fadeOut();
}); });
// Save Add Entry // Save Add Entry
$('#save-add-two').on('click', function () { $('#save-add-two').on('click', function() {
let client_id = $('#add-client-id').val(); let formData = {
let date = $('#add-date').val(); 'client_id': $('#add-client-id').val(),
let warm = $('#add-warm').is(':checked') ? 1 : 0; 'date': $('#add-date').val(),
let lhe_anlieferung = $('#add-lhe-anlieferung').val(); 'is_warm': $('#add-is-warm').is(':checked'),
let lhe_ausgabe = $('#add-lhe-ausgabe').val(); 'lhe_delivery': $('#add-lhe-delivery').val(),
let comment = $('#add-comment').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({ $.ajax({
url: '/add-entry/SecondTableEntry/', url: '/add-entry/SecondTableEntry/',
method: 'POST', method: 'POST',
data: { data: formData,
'client_id': client_id, success: function(response) {
'date': date, // Clear the form
'warm': warm, $('#add-popup-two').find('input, textarea, select').val('');
'lhe_anlieferung': lhe_anlieferung, $('#add-is-warm').prop('checked', false);
'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">
<button class="edit-btn-two">Edit</button>
<button class="delete-btn-two">Delete</button>
</td>
</tr>`;
$('tbody').append(newRow);
$('#add-popup-two').fadeOut(); $('#add-popup-two').fadeOut();
// Reload the table data
loadTableData();
}, },
error: function (xhr) { error: function(xhr) {
alert('Failed to add entry: ' + xhr.responseText); 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,14 +55,24 @@ def table_one_view(request):
# Table Two View (SecondTableEntry) # Table Two View (SecondTableEntry)
def table_two_view(request): def table_two_view(request):
try:
SecondTableEntry = apps.get_model('sheets', 'SecondTableEntry') SecondTableEntry = apps.get_model('sheets', 'SecondTableEntry')
entries_table2 = SecondTableEntry.objects.all() entries = SecondTableEntry.objects.all().order_by('-date')
clients = Client.objects.all() clients = Client.objects.all()
return render(request, 'table_two.html', { return render(request, 'table_two.html', {
'entries_table2': entries_table2, 'entries_table2': entries,
'clients': clients, '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)
def add_entry(request, model_name): def add_entry(request, model_name):
@@ -39,42 +80,74 @@ def add_entry(request, model_name):
try: try:
model = apps.get_model('sheets', model_name) model = apps.get_model('sheets', model_name)
if model_name.lower() == 'client': common_data = {
name = request.POST.get('name', 'New Name') 'client': Client.objects.get(id=request.POST.get('client_id')),
address = request.POST.get('address', '') 'date': request.POST.get('date'),
entry = model.objects.create(name=name, address=address) 'notes': request.POST.get('notes', '')
return JsonResponse({ }
'id': entry.id,
'name': entry.name,
'address': entry.address,
})
client_id = request.POST.get('client_id')
client = Client.objects.get(id=client_id)
age = int(request.POST.get('age', 0))
email = request.POST.get('email', 'example@email.com')
if model_name == 'SecondTableEntry':
# Handle Helium Output (Table Two)
lhe_output = request.POST.get('lhe_output')
entry = model.objects.create( entry = model.objects.create(
client=client, **common_data,
age=age, is_warm=request.POST.get('is_warm') == 'true',
email=email, lhe_delivery=request.POST.get('lhe_delivery', ''),
date_joined=date.today() lhe_output=Decimal(lhe_output) if lhe_output else None
) )
return JsonResponse({ return JsonResponse({
'status': 'success',
'id': entry.id, 'id': entry.id,
'client_name': client.name, 'client_name': entry.client.name,
'age': entry.age, 'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
'email': entry.email, 'is_warm': entry.is_warm,
'date_joined': entry.date_joined.strftime('%Y-%m-%d'), 'lhe_delivery': entry.lhe_delivery,
'lhe_output': str(entry.lhe_output) if entry.lhe_output else '',
'notes': entry.notes
}) })
elif model_name == 'ExcelEntry':
# Parse the date string into a date object
date_str = request.POST.get('date')
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', '')
)
# Prepare the response
response_data = {
'status': 'success',
'id': entry.id,
'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)
# Keep your existing SecondTableEntry code here...
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.save() entry.notes = request.POST.get('notes', '')
return JsonResponse({
'status': 'success',
'id': entry.id,
'name': entry.name,
'address': entry.address,
})
client_id = request.POST.get('client_id') if model_name == 'SecondTableEntry':
client = Client.objects.get(id=client_id) # Handle Helium Output (Table Two)
age = int(request.POST.get('age')) lhe_output = request.POST.get('lhe_output')
email = request.POST.get('email') entry.is_warm = request.POST.get('is_warm') == 'true'
entry.lhe_delivery = request.POST.get('lhe_delivery', '')
entry.client = client entry.lhe_output = Decimal(lhe_output) if lhe_output else None
entry.age = age
entry.email = email
entry.save() entry.save()
return JsonResponse({ return JsonResponse({
'status': 'success', 'status': 'success',
'id': entry.id, 'id': entry.id,
'name': client.name, 'client_name': entry.client.name,
'age': entry.age, 'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
'email': entry.email, 'is_warm': entry.is_warm,
'date_joined': entry.date_joined.strftime('%Y-%m-%d'), 'lhe_delivery': entry.lhe_delivery,
'lhe_output': str(entry.lhe_output) if entry.lhe_output else '',
'notes': entry.notes
}) })
elif model_name == 'ExcelEntry':
# Handle Helium Input (Table One)
date_str = request.POST.get('date')
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.objects.get(id=request.POST.get('client_id'))
entry.date = date_obj
entry.pressure = Decimal(request.POST.get('pressure', 0))
entry.purity = Decimal(request.POST.get('purity', 0))
entry.notes = request.POST.get('notes', '')
entry.save()
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':