diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..8c351d7 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..373d21b 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..a262fa5 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..aaa26e7 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..3bc3b7f 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,34 @@ from django.contrib import admin +from .models import Ingredient, MenuItem, MenuItemIngredient, Order, OrderItem, UserProfile -# Register your models here. +@admin.register(UserProfile) +class UserProfileAdmin(admin.ModelAdmin): + list_display = ('user', 'role') + list_filter = ('role',) + search_fields = ('user__username',) + +class MenuItemIngredientInline(admin.TabularInline): + model = MenuItemIngredient + extra = 1 + +@admin.register(Ingredient) +class IngredientAdmin(admin.ModelAdmin): + list_display = ('name', 'stock_quantity', 'unit') + search_fields = ('name',) + +@admin.register(MenuItem) +class MenuItemAdmin(admin.ModelAdmin): + list_display = ('name', 'price', 'is_active') + inlines = [MenuItemIngredientInline] + search_fields = ('name',) + +class OrderItemInline(admin.TabularInline): + model = OrderItem + extra = 0 + readonly_fields = ('menu_item', 'quantity', 'price_at_order') + +@admin.register(Order) +class OrderAdmin(admin.ModelAdmin): + list_display = ('order_number', 'total_price', 'created_at') + inlines = [OrderItemInline] + readonly_fields = ('order_number', 'total_price', 'created_at', 'customer_notes') diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..5734ee3 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,65 @@ +# Generated by Django 5.2.7 on 2026-02-09 16:12 + +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Ingredient', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('stock_quantity', models.DecimalField(decimal_places=2, default=0.0, max_digits=10)), + ('unit', models.CharField(default='grams', max_length=20)), + ], + ), + migrations.CreateModel( + name='MenuItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('price', models.DecimalField(decimal_places=2, max_digits=10)), + ('description', models.TextField(blank=True)), + ('image_url', models.URLField(blank=True, null=True)), + ('is_active', models.BooleanField(default=True)), + ], + ), + migrations.CreateModel( + name='Order', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order_number', models.CharField(editable=False, max_length=12, unique=True)), + ('created_at', models.DateTimeField(default=django.utils.timezone.now)), + ('total_price', models.DecimalField(decimal_places=2, default=0.0, max_digits=10)), + ('customer_notes', models.TextField(blank=True)), + ], + ), + migrations.CreateModel( + name='MenuItemIngredient', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity_required', models.DecimalField(decimal_places=2, max_digits=10)), + ('ingredient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ingredient')), + ('menu_item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ingredients', to='core.menuitem')), + ], + ), + migrations.CreateModel( + name='OrderItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=1)), + ('price_at_order', models.DecimalField(decimal_places=2, max_digits=10)), + ('menu_item', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='core.menuitem')), + ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='core.order')), + ], + ), + ] diff --git a/core/migrations/0002_userprofile.py b/core/migrations/0002_userprofile.py new file mode 100644 index 0000000..ef447d3 --- /dev/null +++ b/core/migrations/0002_userprofile.py @@ -0,0 +1,24 @@ +# Generated by Django 5.2.7 on 2026-02-09 16:25 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('role', models.CharField(choices=[('manager', 'Manager'), ('cashier', 'Cashier')], default='cashier', max_length=10)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..205652f Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0002_userprofile.cpython-311.pyc b/core/migrations/__pycache__/0002_userprofile.cpython-311.pyc new file mode 100644 index 0000000..abf00b6 Binary files /dev/null and b/core/migrations/__pycache__/0002_userprofile.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..d8d029a 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,65 @@ from django.db import models +from django.db import transaction +from django.utils import timezone +from django.contrib.auth.models import User +import uuid -# Create your models here. +class UserProfile(models.Model): + ROLE_CHOICES = [ + ('manager', 'Manager'), + ('cashier', 'Cashier'), + ] + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') + role = models.CharField(max_length=10, choices=ROLE_CHOICES, default='cashier') + + def __str__(self): + return f"{self.user.username} - {self.get_role_display()}" + +class Ingredient(models.Model): + name = models.CharField(max_length=100, unique=True) + stock_quantity = models.DecimalField(max_digits=10, decimal_places=2, default=0.00) + unit = models.CharField(max_length=20, default="grams") + + def __str__(self): + return f"{self.name} ({self.stock_quantity} {self.unit})" + +class MenuItem(models.Model): + name = models.CharField(max_length=100, unique=True) + price = models.DecimalField(max_digits=10, decimal_places=2) + description = models.TextField(blank=True) + image_url = models.URLField(blank=True, null=True) + is_active = models.BooleanField(default=True) + + def __str__(self): + return self.name + +class MenuItemIngredient(models.Model): + menu_item = models.ForeignKey(MenuItem, related_name='ingredients', on_delete=models.CASCADE) + ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE) + quantity_required = models.DecimalField(max_digits=10, decimal_places=2) + + def __str__(self): + return f"{self.quantity_required} {self.ingredient.unit} of {self.ingredient.name} for {self.menu_item.name}" + +class Order(models.Model): + order_number = models.CharField(max_length=12, unique=True, editable=False) + created_at = models.DateTimeField(default=timezone.now) + total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00) + customer_notes = models.TextField(blank=True) + + def save(self, *args, **kwargs): + if not self.order_number: + self.order_number = str(uuid.uuid4().hex[:8]).upper() + super().save(*args, **kwargs) + + def __str__(self): + return f"Order {self.order_number}" + +class OrderItem(models.Model): + order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE) + menu_item = models.ForeignKey(MenuItem, on_delete=models.PROTECT) + quantity = models.PositiveIntegerField(default=1) + price_at_order = models.DecimalField(max_digits=10, decimal_places=2) + + def __str__(self): + return f"{self.quantity} x {self.menu_item.name}" diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..a14e57d 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,101 @@ +{% load static %} -
- -