diff --git a/admin_panel/admin.py b/admin_panel/admin.py index 577386b..3d7420a 100644 --- a/admin_panel/admin.py +++ b/admin_panel/admin.py @@ -57,7 +57,19 @@ def get_inline_instances(self, request, obj=None): else : return [x for x in unfiltered if isinstance(x,BuyerInline)] +class CategoryAdmin(admin.ModelAdmin): + list_display = ('title', 'slug', 'id', 'is_active',) + list_filter = ('is_active',) + search_fields = ('title',) + prepopulated_fields = {'slug': ('title',)} + ordering = ('title',) + +class HighlightsAdmin(admin.ModelAdmin): + list_display = ('title', 'img', 'id', 'is_active',) + list_filter = ('is_active',) + search_fields = ('title',) + prepopulated_fields = {'slug': ('title',)} admin.site.register(CustomUser, CustomUserAdmin) -admin.site.register(Category) +admin.site.register(Category, CategoryAdmin) admin.site.register(Highlights) diff --git a/admin_panel/migrations/0009_auto_20230730_1750.py b/admin_panel/migrations/0009_auto_20230730_1750.py new file mode 100644 index 0000000..50252a3 --- /dev/null +++ b/admin_panel/migrations/0009_auto_20230730_1750.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.3 on 2023-07-30 17:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('admin_panel', '0008_customuser_mail_is_verified'), + ] + + operations = [ + migrations.AddField( + model_name='category', + name='is_active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='category', + name='slug', + field=models.SlugField(default='ee', max_length=200, unique=True), + preserve_default=False, + ), + ] diff --git a/admin_panel/migrations/0010_highlights_slug.py b/admin_panel/migrations/0010_highlights_slug.py new file mode 100644 index 0000000..7a8e6a0 --- /dev/null +++ b/admin_panel/migrations/0010_highlights_slug.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.3 on 2023-07-30 17:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('admin_panel', '0009_auto_20230730_1750'), + ] + + operations = [ + migrations.AddField( + model_name='highlights', + name='slug', + field=models.SlugField(default='ee', max_length=200, unique=True), + preserve_default=False, + ), + ] diff --git a/admin_panel/migrations/0011_highlights_is_active.py b/admin_panel/migrations/0011_highlights_is_active.py new file mode 100644 index 0000000..ed0c16c --- /dev/null +++ b/admin_panel/migrations/0011_highlights_is_active.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.3 on 2023-07-30 17:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('admin_panel', '0010_highlights_slug'), + ] + + operations = [ + migrations.AddField( + model_name='highlights', + name='is_active', + field=models.BooleanField(default=True), + ), + ] diff --git a/admin_panel/models.py b/admin_panel/models.py index 3238587..2852a4b 100644 --- a/admin_panel/models.py +++ b/admin_panel/models.py @@ -3,6 +3,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django.core.validators import RegexValidator +from django.utils.text import slugify from .managers import CustomUserManager @@ -48,11 +49,23 @@ def __str__(self): class Category(models.Model): title = models.CharField(max_length=255) + slug = models.SlugField(max_length=200, unique=True) + is_active = models.BooleanField(default=True) img = models.ImageField(upload_to='category', blank=True) + class Meta: + ordering = ['title'] + verbose_name_plural = 'Categories' + verbose_name = 'Category' + def __str__(self): return self.title + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + super(Category, self).save(*args, **kwargs) + class Meta: ordering = ['title'] verbose_name_plural = 'Categories' @@ -61,7 +74,14 @@ class Meta: class Highlights(models.Model): title = models.CharField(max_length=255) + slug = models.SlugField(max_length=200, unique=True) img = models.ImageField(upload_to='highlights', blank=True) + is_active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + super(Highlights, self).save(*args, **kwargs) def __str__(self): return self.title diff --git a/buyers_panel/admin.py b/buyers_panel/admin.py index 0b9f79d..23178f6 100644 --- a/buyers_panel/admin.py +++ b/buyers_panel/admin.py @@ -1,16 +1,31 @@ from django.contrib import admin -from buyers_panel.models import BillingAddress, Order, OrderItem +from buyers_panel.models import BillingAddress, Order, OrderItem, Refund, Buyer class OrderItemAdmin(admin.ModelAdmin): model = OrderItem list_display = ['user', 'item', 'quantity',] +class OnlyActiveOrdersFilter(admin.SimpleListFilter): + title = 'Show only active orders' + parameter_name = 'status' + def lookups(self, request, model_admin): + return ( + ('active', 'Active'), + ) + + def queryset(self, request, queryset): + if self.value() == 'active': + return queryset.filter(status__in=('P', 'O')) + return queryset + class OrderAdmin(admin.ModelAdmin): model = Order - list_display = ['id','user', 'shipping_address', 'ordered_date',] + list_display = ['id','user', 'shipping_address', 'ordered_date', 'status'] search_fields = ['ref_code', 'user',] ordering = ('ordered_date',) + filter_horizontal = ('items',) + list_filter = ('status', OnlyActiveOrdersFilter, 'ordered', 'being_delivered', 'received',) class BillingAddressAdmin(admin.ModelAdmin): model = BillingAddress @@ -20,4 +35,6 @@ class BillingAddressAdmin(admin.ModelAdmin): admin.site.register(Order, OrderAdmin) admin.site.register(OrderItem, OrderItemAdmin) -admin.site.register(BillingAddress, BillingAddressAdmin) \ No newline at end of file +admin.site.register(BillingAddress, BillingAddressAdmin) +admin.site.register(Refund) +admin.site.register(Buyer) diff --git a/buyers_panel/migrations/0010_auto_20230730_1712.py b/buyers_panel/migrations/0010_auto_20230730_1712.py new file mode 100644 index 0000000..aad8985 --- /dev/null +++ b/buyers_panel/migrations/0010_auto_20230730_1712.py @@ -0,0 +1,27 @@ +# Generated by Django 3.2.3 on 2023-07-30 17:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('buyers_panel', '0009_auto_20221229_1625'), + ] + + operations = [ + migrations.AlterModelOptions( + name='order', + options={'ordering': ['-id', '-ordered_date'], 'verbose_name': 'Order', 'verbose_name_plural': 'Orders'}, + ), + migrations.AddField( + model_name='order', + name='completed_at', + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AddField( + model_name='order', + name='status', + field=models.CharField(choices=[('P', 'Pending'), ('O', 'Ordered'), ('D', 'Being Delivered'), ('R', 'Received'), ('F', 'Refund Requested')], default='P', max_length=1), + ), + ] diff --git a/buyers_panel/models.py b/buyers_panel/models.py index 4b29028..b0b545f 100644 --- a/buyers_panel/models.py +++ b/buyers_panel/models.py @@ -61,6 +61,14 @@ def get_final_price(self): return self.get_total_item_price() +ORDER_STATUSES = ( + ('P', 'Pending'), + ('O', 'Ordered'), + ('D', 'Being Delivered'), + ('R', 'Received'), + ('F', 'Refund Requested'), +) + class Order(models.Model): user = models.ForeignKey(CustomUser, on_delete=models.CASCADE) ref_code = models.CharField(max_length=120) @@ -73,12 +81,16 @@ class Order(models.Model): ordered_date = models.DateTimeField(editable=False) ordered = models.BooleanField(default=False) being_delivered = models.BooleanField(default=False) + completed_at = models.DateTimeField(null=True, blank=True) received = models.BooleanField(default=False) refund_requested = models.BooleanField(default=False) refund_granted = models.BooleanField(default=False) + status = models.CharField(max_length=1, choices=ORDER_STATUSES, default='P') class Meta: - ordering = ['-id'] + ordering = ['-id', '-ordered_date'] + verbose_name_plural = 'Orders' + verbose_name = 'Order' def __str__(self): return self.user.first_name + ' ' + self.user.email @@ -88,6 +100,10 @@ def save(self, *args, **kwargs): if not self.id: self.ordered_date = timezone.now() self.start_date = timezone.now() + if self.completed_at: + self.status = 'R' + if self.status == 'R' and not self.completed_at: + self.completed_at = timezone.now() return super(Order, self).save(*args, **kwargs) def get_total(self): diff --git a/common/tuples.py b/common/tuples.py new file mode 100644 index 0000000..2f06bbe --- /dev/null +++ b/common/tuples.py @@ -0,0 +1,10 @@ +from collections import namedtuple + +ORDER_STATUSES = namedtuple('ORDER_STATUSES', ['PENDING', 'ACCEPTED', 'REJECTED', 'CANCELLED'])._make(range(5)) + +ORDER_STATUSES = ( + (ORDER_STATUSES.PENDING, 'PENDING'), + (ORDER_STATUSES.ACCEPTED, 'ACCEPTED'), + (ORDER_STATUSES.REJECTED, 'REJECTED'), + (ORDER_STATUSES.CANCELLED, 'CANCELLED'), +) diff --git a/delivery_panel/admin.py b/delivery_panel/admin.py index 8c38f3f..867fcee 100644 --- a/delivery_panel/admin.py +++ b/delivery_panel/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from delivery_panel.models import Deliverer + +admin.site.register(Deliverer) -# Register your models here. diff --git a/grocers_panel/admin.py b/grocers_panel/admin.py index 3f6631e..bde88b4 100644 --- a/grocers_panel/admin.py +++ b/grocers_panel/admin.py @@ -1,13 +1,23 @@ from django.contrib import admin -from grocers_panel.models import Shop, FoodMeal, Meal, Rating +from grocers_panel.models import Shop, FoodMeal, Meal, Rating, Grocer +from djangoql.admin import DjangoQLSearchMixin - -class MealAdmin(admin.ModelAdmin): +class MealAdmin(DjangoQLSearchMixin, admin.ModelAdmin): model = Meal + list_display = ['name', 'price'] + search_fields = ('name', 'id',) + ordering = ('name',) + list_filter = ('price',) + class FoodAdmin(admin.ModelAdmin): model = FoodMeal + list_display = ['category', 'id'] + search_fields = ('category', 'id',) + ordering = ('category',) + filter_horizontal = ('meals',) + class ShopAdmin(admin.ModelAdmin): @@ -15,6 +25,7 @@ class ShopAdmin(admin.ModelAdmin): list_display = ['name', 'tag_list'] search_fields = ('name', 'id',) ordering = ('name',) + filter_horizontal = ('tags',) def get_queryset(self, request): return super().get_queryset(request).prefetch_related('tags') @@ -27,3 +38,5 @@ def tag_list(self, obj): admin.site.register(FoodMeal, FoodAdmin) admin.site.register(Meal, MealAdmin) admin.site.register(Shop, ShopAdmin) +admin.site.register(Grocer) + diff --git a/grocers_panel/models.py b/grocers_panel/models.py index 737398f..cbc06dc 100644 --- a/grocers_panel/models.py +++ b/grocers_panel/models.py @@ -72,8 +72,6 @@ class Shop(models.Model): ) name = models.CharField(max_length=255) grocer = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True) - # rating = models.ManyToManyField(CustomUser, through=Rating) - # ratings = models.IntegerField(default=0) img = models.ImageField(upload_to='shop/%Y/%m/%d', blank=True) distance = models.FloatField() tags = TaggableManager() diff --git a/grocery_app/settings.py b/grocery_app/settings.py index 5b656af..6660260 100644 --- a/grocery_app/settings.py +++ b/grocery_app/settings.py @@ -50,6 +50,7 @@ 'storages', 'django_countries', 'multiselectfield', + 'djangoql', 'grocery_api.apps.GroceryApiConfig', 'admin_panel.apps.AdminPanelConfig', diff --git a/requirements-dev.txt b/requirements-dev.txt index cea9c2a..e739221 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -44,4 +44,5 @@ django-storages==1.12.3 django-countries==7.2.1 django-multiselectfield==0.1.12 django-taggit-serializer==0.1.7 -coreapi==2.3.3 \ No newline at end of file +coreapi==2.3.3 +djangoql==0.17.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 16d23fe..eba561d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -46,4 +46,5 @@ django-multiselectfield==0.1.12 gunicorn==20.1.0 django-heroku==0.3.1 django-taggit-serializer==0.1.7 -coreapi==2.3.3 \ No newline at end of file +coreapi==2.3.3 +djangoql==0.17.1 \ No newline at end of file