38323-vm/core/views.py
2026-02-09 16:33:02 +00:00

147 lines
5.7 KiB
Python

from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse
from django.db import transaction
from django.db.models import Sum, F
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.models import User
from .models import Ingredient, MenuItem, MenuItemIngredient, Order, OrderItem, UserProfile
import json
def is_manager(user):
return user.is_authenticated and hasattr(user, 'profile') and user.profile.role == 'manager'
def is_cashier(user):
return user.is_authenticated and hasattr(user, 'profile') and user.profile.role == 'cashier'
def manager_required(view_func):
return user_passes_test(is_manager, login_url='login')(view_func)
def cashier_or_manager_required(view_func):
return user_passes_test(lambda u: is_manager(u) or is_cashier(u), login_url='login')(view_func)
def login_view(request):
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
if is_manager(user):
return redirect('dashboard')
return redirect('pos')
else:
form = AuthenticationForm()
return render(request, 'core/login.html', {'form': form})
def logout_view(request):
logout(request)
return redirect('login')
def home(request):
"""Redirect home to login or dashboard/pos based on role."""
if request.user.is_authenticated:
if is_manager(request.user):
return redirect('dashboard')
return redirect('pos')
return render(request, "core/index.html")
@cashier_or_manager_required
def pos_view(request):
"""Cashier POS interface."""
menu_items = MenuItem.objects.filter(is_active=True)
return render(request, "core/pos.html", {"menu_items": menu_items})
@cashier_or_manager_required
def create_order(request):
"""Handle order creation and stock deduction."""
if request.method == "POST":
try:
data = json.loads(request.body)
cart = data.get("cart", [])
notes = data.get("notes", "")
if not cart:
return JsonResponse({"success": False, "error": "Cart is empty"}, status=400)
with transaction.atomic():
order = Order.objects.create(customer_notes=notes)
total_price = 0
for item in cart:
menu_item = get_object_or_404(MenuItem, id=item["id"])
quantity = int(item["quantity"])
# Deduct stock
for recipe_item in menu_item.ingredients.all():
required_qty = recipe_item.quantity_required * quantity
ingredient = recipe_item.ingredient
if ingredient.stock_quantity < required_qty:
raise Exception(f"Insufficient stock for {ingredient.name}")
ingredient.stock_quantity = F('stock_quantity') - required_qty
ingredient.save()
# Create OrderItem
OrderItem.objects.create(
order=order,
menu_item=menu_item,
quantity=quantity,
price_at_order=menu_item.price
)
total_price += menu_item.price * quantity
order.total_price = total_price
order.save()
return JsonResponse({"success": True, "order_number": order.order_number})
except Exception as e:
return JsonResponse({"success": False, "error": str(e)}, status=400)
return JsonResponse({"success": False, "error": "Invalid request"}, status=405)
@cashier_or_manager_required
def receipt_view(request, order_number):
"""Printable receipt view."""
order = get_object_or_404(Order, order_number=order_number)
return render(request, "core/receipt.html", {"order": order})
@manager_required
def dashboard_view(request):
"""Manager dashboard for stock and reports."""
ingredients = Ingredient.objects.all()
# Summary of last 30 orders
orders = Order.objects.prefetch_related('items__menu_item').order_by('-created_at')[:50]
total_sales = Order.objects.aggregate(Sum('total_price'))['total_price__sum'] or 0
return render(request, "core/dashboard.html", {
"ingredients": ingredients,
"orders": orders,
"total_sales": total_sales,
})
@manager_required
def manage_users(request):
"""Manager only: Create and view accounts."""
users = User.objects.all().select_related('profile')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
role = request.POST.get('role')
if username and password and role:
if User.objects.filter(username=username).exists():
messages.error(request, f"User {username} already exists.")
else:
user = User.objects.create_user(username=username, password=password)
profile, created = UserProfile.objects.get_or_create(user=user)
profile.role = role
profile.save()
messages.success(request, f"User {username} created as {role}.")
return redirect('manage_users')
else:
messages.error(request, "Please fill all fields.")
return render(request, 'core/user_management.html', {'users': users})