353 lines
14 KiB
Python
353 lines
14 KiB
Python
from django.shortcuts import render ,redirect
|
|
from django.db.models import Sum, Value, DecimalField
|
|
from django.http import JsonResponse
|
|
from django.db.models import Q
|
|
from decimal import Decimal, InvalidOperation
|
|
from django.apps import apps
|
|
from datetime import date, datetime
|
|
from django.utils import timezone
|
|
from .models import Client, SecondTableEntry
|
|
from django.db.models import Sum
|
|
from django.urls import reverse
|
|
from django.db.models.functions import Coalesce
|
|
from .forms import BetriebskostenForm
|
|
from .models import Betriebskosten
|
|
from django.utils.dateparse import parse_date
|
|
|
|
|
|
# Clients Page (Main)
|
|
from django.shortcuts import render
|
|
from django.db.models import Sum
|
|
from datetime import datetime
|
|
from .models import Client, SecondTableEntry
|
|
|
|
def clients_list(request):
|
|
# Get all clients
|
|
clients = Client.objects.all()
|
|
|
|
# Get all years available in SecondTableEntry
|
|
available_years_qs = SecondTableEntry.objects.dates('date', 'year', order='DESC')
|
|
available_years = [y.year for y in available_years_qs]
|
|
|
|
# Determine selected year
|
|
year_param = request.GET.get('year')
|
|
if year_param:
|
|
selected_year = int(year_param)
|
|
else:
|
|
# If no year in GET, default to latest available year or current year if DB empty
|
|
selected_year = available_years[0] if available_years else datetime.now().year
|
|
|
|
# Prepare monthly totals per client
|
|
monthly_data = []
|
|
for client in clients:
|
|
monthly_totals = []
|
|
for month in range(1, 13):
|
|
total = SecondTableEntry.objects.filter(
|
|
client=client,
|
|
date__year=selected_year,
|
|
date__month=month
|
|
).aggregate(
|
|
total=Coalesce(Sum('lhe_output'), Value(0, output_field=DecimalField()))
|
|
)['total']
|
|
monthly_totals.append(total)
|
|
|
|
monthly_data.append({
|
|
'client': client,
|
|
'monthly_totals': monthly_totals,
|
|
'year_total': sum(monthly_totals)
|
|
})
|
|
|
|
return render(request, 'clients_table.html', {
|
|
'monthly_data': monthly_data,
|
|
'current_year': selected_year,
|
|
'available_years': available_years,
|
|
'months': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
|
})
|
|
# Table One View (ExcelEntry)
|
|
def table_one_view(request):
|
|
ExcelEntry = apps.get_model('sheets', 'ExcelEntry')
|
|
entries_table1 = ExcelEntry.objects.all().select_related('client')
|
|
clients = Client.objects.all()
|
|
return render(request, 'table_one.html', {
|
|
'entries_table1': entries_table1,
|
|
'clients': clients,
|
|
})
|
|
|
|
|
|
# Table Two View (SecondTableEntry)
|
|
def table_two_view(request):
|
|
try:
|
|
SecondTableEntry = apps.get_model('sheets', 'SecondTableEntry')
|
|
entries = SecondTableEntry.objects.all().order_by('-date')
|
|
clients = Client.objects.all()
|
|
|
|
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)
|
|
def add_entry(request, model_name):
|
|
if request.method == 'POST':
|
|
try:
|
|
model = apps.get_model('sheets', model_name)
|
|
|
|
if model_name == 'SecondTableEntry':
|
|
# Handle date conversion
|
|
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):
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Invalid date format. Use YYYY-MM-DD'
|
|
}, status=400)
|
|
|
|
# Handle Helium Output (Table Two)
|
|
lhe_output = request.POST.get('lhe_output')
|
|
entry = model.objects.create(
|
|
client=Client.objects.get(id=request.POST.get('client_id')),
|
|
date=date_obj,
|
|
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,
|
|
notes=request.POST.get('notes', '')
|
|
)
|
|
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'id': entry.id,
|
|
'client_name': entry.client.name,
|
|
'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
|
|
})
|
|
|
|
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:
|
|
return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
|
|
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
|
# Update Entry (Generic)
|
|
def update_entry(request, model_name):
|
|
if request.method == 'POST':
|
|
try:
|
|
model = apps.get_model('sheets', model_name)
|
|
entry_id = int(request.POST.get('id'))
|
|
entry = model.objects.get(id=entry_id)
|
|
|
|
# Common updates for both models
|
|
entry.client = Client.objects.get(id=request.POST.get('client_id'))
|
|
entry.notes = request.POST.get('notes', '')
|
|
|
|
# Handle date properly for both models
|
|
date_str = request.POST.get('date')
|
|
if date_str:
|
|
try:
|
|
entry.date = datetime.strptime(date_str, '%Y-%m-%d').date()
|
|
except ValueError:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Invalid date format. Use YYYY-MM-DD'
|
|
}, status=400)
|
|
|
|
if model_name == 'SecondTableEntry':
|
|
# Handle Helium Output specific fields
|
|
entry.is_warm = request.POST.get('is_warm') == 'true'
|
|
entry.lhe_delivery = request.POST.get('lhe_delivery', '')
|
|
|
|
lhe_output = request.POST.get('lhe_output')
|
|
try:
|
|
entry.lhe_output = Decimal(lhe_output) if lhe_output else None
|
|
except InvalidOperation:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Invalid LHe Output value'
|
|
}, status=400)
|
|
|
|
entry.save()
|
|
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'id': entry.id,
|
|
'client_name': entry.client.name,
|
|
'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
|
|
})
|
|
|
|
elif model_name == 'ExcelEntry':
|
|
# Handle Helium Input specific fields
|
|
try:
|
|
entry.pressure = Decimal(request.POST.get('pressure', 0))
|
|
entry.purity = Decimal(request.POST.get('purity', 0))
|
|
except InvalidOperation:
|
|
return JsonResponse({
|
|
'status': 'error',
|
|
'message': 'Invalid pressure or purity value'
|
|
}, status=400)
|
|
|
|
entry.save()
|
|
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'id': entry.id,
|
|
'client_name': entry.client.name,
|
|
'date': entry.date.strftime('%Y-%m-%d') if entry.date else '',
|
|
'pressure': str(entry.pressure),
|
|
'purity': str(entry.purity),
|
|
'notes': entry.notes
|
|
})
|
|
|
|
except model.DoesNotExist:
|
|
return JsonResponse({'status': 'error', 'message': 'Entry not found'}, status=404)
|
|
except Exception as e:
|
|
return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
|
|
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid request method'}, status=400)
|
|
# Delete Entry (Generic)
|
|
def delete_entry(request, model_name):
|
|
if request.method == 'POST':
|
|
try:
|
|
model = apps.get_model('sheets', model_name)
|
|
entry_id = request.POST.get('id')
|
|
entry = model.objects.get(id=entry_id)
|
|
entry.delete()
|
|
return JsonResponse({'status': 'success', 'message': 'Entry deleted'})
|
|
|
|
except model.DoesNotExist:
|
|
return JsonResponse({'status': 'error', 'message': 'Entry not found'}, status=404)
|
|
except Exception as e:
|
|
return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
|
|
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid request'}, status=400)
|
|
|
|
def betriebskosten_list(request):
|
|
items = Betriebskosten.objects.all().order_by('-buchungsdatum')
|
|
return render(request, 'betriebskosten_list.html', {'items': items})
|
|
|
|
def betriebskosten_create(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
entry_id = request.POST.get('id')
|
|
if entry_id:
|
|
# Update existing entry
|
|
entry = Betriebskosten.objects.get(id=entry_id)
|
|
else:
|
|
# Create new entry
|
|
entry = Betriebskosten()
|
|
|
|
# Get form data
|
|
buchungsdatum_str = request.POST.get('buchungsdatum')
|
|
rechnungsnummer = request.POST.get('rechnungsnummer')
|
|
kostentyp = request.POST.get('kostentyp')
|
|
betrag = request.POST.get('betrag')
|
|
beschreibung = request.POST.get('beschreibung')
|
|
gas_volume = request.POST.get('gas_volume')
|
|
|
|
# Validate required fields
|
|
if not all([buchungsdatum_str, rechnungsnummer, kostentyp, betrag]):
|
|
return JsonResponse({'status': 'error', 'message': 'All required fields must be filled'})
|
|
|
|
# Convert date string to date object
|
|
try:
|
|
buchungsdatum = parse_date(buchungsdatum_str)
|
|
if not buchungsdatum:
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid date format'})
|
|
except (ValueError, TypeError):
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid date format'})
|
|
|
|
# Set entry values
|
|
entry.buchungsdatum = buchungsdatum
|
|
entry.rechnungsnummer = rechnungsnummer
|
|
entry.kostentyp = kostentyp
|
|
entry.betrag = betrag
|
|
entry.beschreibung = beschreibung
|
|
|
|
# Only set gas_volume if kostentyp is helium and gas_volume is provided
|
|
if kostentyp == 'helium' and gas_volume:
|
|
entry.gas_volume = gas_volume
|
|
else:
|
|
entry.gas_volume = None
|
|
|
|
entry.save()
|
|
|
|
return JsonResponse({
|
|
'status': 'success',
|
|
'id': entry.id,
|
|
'buchungsdatum': entry.buchungsdatum.strftime('%Y-%m-%d'),
|
|
'rechnungsnummer': entry.rechnungsnummer,
|
|
'kostentyp_display': entry.get_kostentyp_display(),
|
|
'gas_volume': str(entry.gas_volume) if entry.gas_volume else '-',
|
|
'betrag': str(entry.betrag),
|
|
'beschreibung': entry.beschreibung or ''
|
|
})
|
|
|
|
except Exception as e:
|
|
return JsonResponse({'status': 'error', 'message': str(e)})
|
|
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid request method'})
|
|
|
|
def betriebskosten_delete(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
entry_id = request.POST.get('id')
|
|
entry = Betriebskosten.objects.get(id=entry_id)
|
|
entry.delete()
|
|
return JsonResponse({'status': 'success'})
|
|
except Betriebskosten.DoesNotExist:
|
|
return JsonResponse({'status': 'error', 'message': 'Entry not found'})
|
|
except Exception as e:
|
|
return JsonResponse({'status': 'error', 'message': str(e)})
|
|
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid request method'}) |