From 856b8ae3fe77b688896023a20b6248cdee3e2f6a Mon Sep 17 00:00:00 2001 From: "ahmetbahadircol@gmail.com" Date: Fri, 10 Dec 2021 15:55:32 +0300 Subject: [PATCH 1/2] Added serializers.py, managers.py, views.py and filters.py files to every apps --- ecommerce/baskets/filters.py | 25 +++ ecommerce/baskets/managers.py | 17 ++ ecommerce/baskets/migrations/0001_initial.py | 12 +- .../migrations/0002_auto_20211205_0953.py | 37 ---- ecommerce/baskets/models.py | 2 + ecommerce/baskets/serializers.py | 45 +++++ ecommerce/baskets/views.py | 32 +++- ecommerce/core/migrations/__init__.py | 0 ecommerce/customers/filters.py | 17 ++ .../customers/migrations/0001_initial.py | 167 ++++++++---------- .../migrations/0002_address_city_country.py | 65 ------- .../migrations/0003_auto_20211203_2031.py | 24 --- .../migrations/0004_alter_address_district.py | 18 -- .../migrations/0005_auto_20211205_0953.py | 34 ---- ecommerce/customers/serializers.py | 52 ++++++ ecommerce/customers/views.py | 32 +++- ecommerce/ecommerce/urls.py | 13 ++ ecommerce/orders/managers.py | 15 ++ ecommerce/orders/migrations/0001_initial.py | 16 +- .../migrations/0002_auto_20211205_0953.py | 38 ---- ecommerce/orders/serializers.py | 89 ++++++++++ ecommerce/orders/views.py | 47 ++++- ecommerce/payments/migrations/0001_initial.py | 6 +- ecommerce/products/filters.py | 1 + ecommerce/products/managers.py | 2 +- ecommerce/products/migrations/0001_initial.py | 45 ++++- .../products/migrations/0002_price_stock.py | 42 ----- .../migrations/0003_auto_20211203_1919.py | 31 ---- .../0004_alter_product_categories.py | 18 -- ecommerce/products/serializers.py | 2 - 30 files changed, 513 insertions(+), 431 deletions(-) create mode 100644 ecommerce/baskets/filters.py create mode 100644 ecommerce/baskets/managers.py delete mode 100644 ecommerce/baskets/migrations/0002_auto_20211205_0953.py create mode 100644 ecommerce/baskets/serializers.py delete mode 100644 ecommerce/core/migrations/__init__.py create mode 100644 ecommerce/customers/filters.py delete mode 100644 ecommerce/customers/migrations/0002_address_city_country.py delete mode 100644 ecommerce/customers/migrations/0003_auto_20211203_2031.py delete mode 100644 ecommerce/customers/migrations/0004_alter_address_district.py delete mode 100644 ecommerce/customers/migrations/0005_auto_20211205_0953.py create mode 100644 ecommerce/customers/serializers.py create mode 100644 ecommerce/orders/managers.py delete mode 100644 ecommerce/orders/migrations/0002_auto_20211205_0953.py create mode 100644 ecommerce/orders/serializers.py delete mode 100644 ecommerce/products/migrations/0002_price_stock.py delete mode 100644 ecommerce/products/migrations/0003_auto_20211203_1919.py delete mode 100644 ecommerce/products/migrations/0004_alter_product_categories.py diff --git a/ecommerce/baskets/filters.py b/ecommerce/baskets/filters.py new file mode 100644 index 0000000..06d9e91 --- /dev/null +++ b/ecommerce/baskets/filters.py @@ -0,0 +1,25 @@ +from django.db.models import Q +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ + +from baskets.models import Basket, BasketItem + + +class BasketFilter(filters.FilterSet): + customer = filters.CharFilter(label=_("Customer"), method="filter_name") + + class Meta: + model = Basket + fields = ("customer", "status") + + def filter_name(self, name, qs, value): + return qs.filter(Q(customer__first_name__icontains=replaced_value) | Q(customer__first_name__icontains=value)) + + +class BasketItemFilter(filters.FilterSet): + product = filters.CharFilter(label=_("Product"), method="filter_name") + + class Meta: + model = BasketItem + fields = ("basket", "product", "quantity", "price") + diff --git a/ecommerce/baskets/managers.py b/ecommerce/baskets/managers.py new file mode 100644 index 0000000..e1828f1 --- /dev/null +++ b/ecommerce/baskets/managers.py @@ -0,0 +1,17 @@ +from django.db import models + + +class BasketQuerySet(models.QuerySet): + def banner_products(self): + """ + BasketItem can not be less then 10 and quantity greater or equal to 100 + """ + return self.filter(basketitem__quantity__gte=10, basketitem__quantity__lt=100) + + def basket_status(self): + """ + Basket Status can not be submitted + """ + return self.filter.exclude(basket__status="submitted") + + diff --git a/ecommerce/baskets/migrations/0001_initial.py b/ecommerce/baskets/migrations/0001_initial.py index 79a58d7..e582ccb 100644 --- a/ecommerce/baskets/migrations/0001_initial.py +++ b/ecommerce/baskets/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.9 on 2021-12-03 17:37 +# Generated by Django 3.2.9 on 2021-12-08 12:41 from django.conf import settings from django.db import migrations, models @@ -10,7 +10,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('products', '0003_auto_20211203_1919'), + ('products', '__first__'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] @@ -21,8 +21,8 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('status', models.CharField(choices=[('open', 'Open'), ('submitted', 'Submitted'), ('merged', 'Merged')], max_length=10, verbose_name='Basket Status')), - ('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Customer')), + ('status', models.CharField(choices=[('open', 'Open'), ('submitted', 'Submitted'), ('merged', 'Merged')], default='open', max_length=10, verbose_name='Basket Status')), + ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Customer')), ], options={ 'verbose_name': 'Basket', @@ -37,8 +37,8 @@ class Migration(migrations.Migration): ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), ('quantity', models.PositiveIntegerField(verbose_name='Quantity')), ('price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Price')), - ('basket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='baskets.basket', verbose_name='Basket')), - ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.product', verbose_name='Product')), + ('basket', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='baskets.basket', verbose_name='Basket')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product')), ], options={ 'verbose_name': 'Basket item', diff --git a/ecommerce/baskets/migrations/0002_auto_20211205_0953.py b/ecommerce/baskets/migrations/0002_auto_20211205_0953.py deleted file mode 100644 index 17bcf3b..0000000 --- a/ecommerce/baskets/migrations/0002_auto_20211205_0953.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-05 06:53 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('products', '0004_alter_product_categories'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('baskets', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='basket', - name='customer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Customer'), - ), - migrations.AlterField( - model_name='basket', - name='status', - field=models.CharField(choices=[('open', 'Open'), ('submitted', 'Submitted'), ('merged', 'Merged')], default='open', max_length=10, verbose_name='Basket Status'), - ), - migrations.AlterField( - model_name='basketitem', - name='basket', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='baskets.basket', verbose_name='Basket'), - ), - migrations.AlterField( - model_name='basketitem', - name='product', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product'), - ), - ] diff --git a/ecommerce/baskets/models.py b/ecommerce/baskets/models.py index 4f109d5..df341ee 100644 --- a/ecommerce/baskets/models.py +++ b/ecommerce/baskets/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ +from baskets.managers import BasketQuerySet from core.models import BaseAbstractModel from customers.models import Customer from baskets import enums @@ -15,6 +16,7 @@ class Basket(BaseAbstractModel): on_delete=models.PROTECT, null=True, blank=True) status = models.CharField(choices=enums.BasketStatus.choices, max_length=10, verbose_name=_("Basket Status"), default=enums.BasketStatus.OPEN) + objects = BasketQuerySet.as_manager() class Meta: verbose_name = _("Basket") diff --git a/ecommerce/baskets/serializers.py b/ecommerce/baskets/serializers.py new file mode 100644 index 0000000..5209d71 --- /dev/null +++ b/ecommerce/baskets/serializers.py @@ -0,0 +1,45 @@ +from rest_framework import serializers +from baskets.models import Basket, BasketItem +from customers.serializers import CustomerSerializer +from products.serializers import ProductSerializer + + +class BasketSerializer(serializers.ModelSerializer): + """ + Basket Serializer + """ + class Meta: + model = Basket + fields = ["customer", "status"] + + +class BasketItemSerializer(serializers.ModelSerializer): + """ + Basket Item Serializer + """ + class Meta: + model = BasketItem + fields = ["basket", "product", "quantity", "price"] + + +class BasketDetailedSerializer(serializers.ModelSerializer): + """ + Basket Detailed Serializer for Customer + """ + customer = CustomerSerializer() # TODO: Add Customer Serializer! + + class Meta: + model = Basket + fields = ["customer", "status"] + + +class BasketItemDetailedSerializer(serializers.ModelSerializer): + """ + Basket Item Detailed Serializer for Product and Basket + """ + basket = BasketSerializer() + product = ProductSerializer() + + class Meta: + model = BasketItem + fields = ["basket", "product", "quantity", "price"] \ No newline at end of file diff --git a/ecommerce/baskets/views.py b/ecommerce/baskets/views.py index 91ea44a..77ac741 100644 --- a/ecommerce/baskets/views.py +++ b/ecommerce/baskets/views.py @@ -1,3 +1,31 @@ -from django.shortcuts import render +from rest_framework import viewsets -# Create your views here. +from baskets.filters import BasketFilter +from core.mixins import DetailedViewSetMixin +from baskets.serializers import * + + +class BasketViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + """ + Detailed ViewSet for Basket + """ + queryset = Basket.objects.all() + serializer_class = BasketSerializer + filterset_class = BasketFilter # TODO: basket için filter ekle + serializer_action_classes = { + "detailed_list": BasketDetailedSerializer, + "detailed": BasketDetailedSerializer, + } + + +class BasketItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + """ + Detailed ViewSet for BasketItem + """ + queryset = BasketItem.objects.all() + serializer_class = BasketItemSerializer + filterset_class = BasketFilter # TODO: basketitem için filter ekle + serializer_action_classes = { + "detailed_list": BasketItemDetailedSerializer, + "detailed": BasketItemDetailedSerializer, + } \ No newline at end of file diff --git a/ecommerce/core/migrations/__init__.py b/ecommerce/core/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ecommerce/customers/filters.py b/ecommerce/customers/filters.py new file mode 100644 index 0000000..97a8841 --- /dev/null +++ b/ecommerce/customers/filters.py @@ -0,0 +1,17 @@ +from django.db.models import Q +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ + +from customers.models import Customer + + +class CustomerFilter(filters.FilterSet): + name = filters.CharFilter(label=_("First Name"), method="filter_name") + + class Meta: + model = Customer + fields = ("first_name", "last_name", "email") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(first_name__icontains=replaced_value) | Q(first_name__icontains=value)) diff --git a/ecommerce/customers/migrations/0001_initial.py b/ecommerce/customers/migrations/0001_initial.py index a691fbb..d551046 100644 --- a/ecommerce/customers/migrations/0001_initial.py +++ b/ecommerce/customers/migrations/0001_initial.py @@ -1,8 +1,11 @@ -# Generated by Django 3.2.9 on 2021-11-28 09:32 +# Generated by Django 3.2.9 on 2021-12-08 12:44 +import core.utils import customers.managers +from django.conf import settings import django.contrib.auth.validators from django.db import migrations, models +import django.db.models.deletion import django.utils.timezone @@ -11,111 +14,81 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ("auth", "0012_alter_user_first_name_max_length"), + ('auth', '0012_alter_user_first_name_max_length'), ] operations = [ migrations.CreateModel( - name="Customer", + name='Customer', fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("password", models.CharField(max_length=128, verbose_name="password")), - ( - "last_login", - models.DateTimeField( - blank=True, null=True, verbose_name="last login" - ), - ), - ( - "is_superuser", - models.BooleanField( - default=False, - help_text="Designates that this user has all permissions without explicitly assigning them.", - verbose_name="superuser status", - ), - ), - ( - "first_name", - models.CharField( - blank=True, max_length=150, verbose_name="first name" - ), - ), - ( - "last_name", - models.CharField( - blank=True, max_length=150, verbose_name="last name" - ), - ), - ( - "email", - models.EmailField( - max_length=254, - unique=True, - validators=[ - django.contrib.auth.validators.UnicodeUsernameValidator() - ], - verbose_name="email address", - ), - ), - ( - "is_staff", - models.BooleanField( - default=False, - help_text="Designates whether the user can log into this admin site.", - verbose_name="staff status", - ), - ), - ( - "is_active", - models.BooleanField( - default=True, - help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", - verbose_name="active", - ), - ), - ( - "date_joined", - models.DateTimeField( - default=django.utils.timezone.now, verbose_name="date joined" - ), - ), - ( - "groups", - models.ManyToManyField( - blank=True, - help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", - related_name="user_set", - related_query_name="user", - to="auth.Group", - verbose_name="groups", - ), - ), - ( - "user_permissions", - models.ManyToManyField( - blank=True, - help_text="Specific permissions for this user.", - related_name="user_set", - related_query_name="user", - to="auth.Permission", - verbose_name="user permissions", - ), - ), + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(max_length=254, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), ], options={ - "verbose_name": "customer", - "verbose_name_plural": "customers", + 'verbose_name': 'customer', + 'verbose_name_plural': 'customers', }, managers=[ - ("objects", customers.managers.CustomerManager()), + ('objects', customers.managers.CustomerManager()), ], ), + migrations.CreateModel( + name='Country', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('name', models.CharField(max_length=255, verbose_name='Country')), + ], + options={ + 'verbose_name': 'country', + 'verbose_name_plural': 'countries', + }, + ), + migrations.CreateModel( + name='City', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('name', models.CharField(max_length=255)), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='customers.country', verbose_name='Country')), + ], + options={ + 'verbose_name': 'city', + 'verbose_name_plural': 'cities', + }, + ), + migrations.CreateModel( + name='Address', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('full_name', models.CharField(max_length=255, verbose_name='Full Name')), + ('line_1', models.CharField(max_length=255, verbose_name='Address Line 1')), + ('line_2', models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2')), + ('phone', models.CharField(help_text='Phone number must be entered in the format: +901234567890. ', max_length=20, validators=[core.utils.PhoneNumberValidator()], verbose_name='Phone Number')), + ('district', models.CharField(max_length=255, verbose_name='District')), + ('zipcode', models.CharField(max_length=20, verbose_name='Zip Code')), + ('is_default', models.BooleanField(default=False)), + ('city', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='customers.city', verbose_name='City')), + ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Customer')), + ], + options={ + 'verbose_name': 'address', + 'verbose_name_plural': 'addresses', + }, + ), ] diff --git a/ecommerce/customers/migrations/0002_address_city_country.py b/ecommerce/customers/migrations/0002_address_city_country.py deleted file mode 100644 index 1f4de99..0000000 --- a/ecommerce/customers/migrations/0002_address_city_country.py +++ /dev/null @@ -1,65 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-03 16:34 - -import customers.models -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('customers', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Country', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('name', models.CharField(max_length=255, verbose_name='Country')), - ], - options={ - 'verbose_name': 'country', - 'verbose_name_plural': 'countries', - }, - ), - migrations.CreateModel( - name='City', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('name', models.CharField(max_length=255)), - ('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='customers.country', verbose_name='Country')), - ], - options={ - 'verbose_name': 'city', - 'verbose_name_plural': 'cities', - }, - ), - migrations.CreateModel( - name='Address', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('full_name', models.CharField(blank=True, max_length=255, verbose_name='Full Name')), - ('line_1', models.CharField(max_length=255, verbose_name='Address Line 1')), - ('line_2', models.CharField(blank=True, max_length=255, verbose_name='Address Line 2')), - ('phone', models.CharField(max_length=20, validators=[customers.models.PhoneNumberValidator()], verbose_name='Phone Number')), - ('district', models.CharField(blank=True, max_length=255, verbose_name='District')), - ('zipcode', models.CharField(blank=True, max_length=20, verbose_name='Zip Code')), - ('is_default', models.BooleanField(default=False)), - ('city', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='customers.city', verbose_name='City')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Customer')), - ], - options={ - 'verbose_name': 'address', - 'verbose_name_plural': 'addresses', - }, - ), - ] diff --git a/ecommerce/customers/migrations/0003_auto_20211203_2031.py b/ecommerce/customers/migrations/0003_auto_20211203_2031.py deleted file mode 100644 index d7e465e..0000000 --- a/ecommerce/customers/migrations/0003_auto_20211203_2031.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-03 17:31 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('customers', '0002_address_city_country'), - ] - - operations = [ - migrations.AlterField( - model_name='address', - name='city', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='customers.city', verbose_name='City'), - ), - migrations.AlterField( - model_name='city', - name='country', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='customers.country', verbose_name='Country'), - ), - ] diff --git a/ecommerce/customers/migrations/0004_alter_address_district.py b/ecommerce/customers/migrations/0004_alter_address_district.py deleted file mode 100644 index 1b80f6c..0000000 --- a/ecommerce/customers/migrations/0004_alter_address_district.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-04 00:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('customers', '0003_auto_20211203_2031'), - ] - - operations = [ - migrations.AlterField( - model_name='address', - name='district', - field=models.CharField(max_length=255, verbose_name='District'), - ), - ] diff --git a/ecommerce/customers/migrations/0005_auto_20211205_0953.py b/ecommerce/customers/migrations/0005_auto_20211205_0953.py deleted file mode 100644 index 431b355..0000000 --- a/ecommerce/customers/migrations/0005_auto_20211205_0953.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-05 06:53 - -import core.utils -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('customers', '0004_alter_address_district'), - ] - - operations = [ - migrations.AlterField( - model_name='address', - name='full_name', - field=models.CharField(max_length=255, verbose_name='Full Name'), - ), - migrations.AlterField( - model_name='address', - name='line_2', - field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2'), - ), - migrations.AlterField( - model_name='address', - name='phone', - field=models.CharField(help_text='Phone number must be entered in the format: +901234567890. ', max_length=20, validators=[core.utils.PhoneNumberValidator()], verbose_name='Phone Number'), - ), - migrations.AlterField( - model_name='address', - name='zipcode', - field=models.CharField(max_length=20, verbose_name='Zip Code'), - ), - ] diff --git a/ecommerce/customers/serializers.py b/ecommerce/customers/serializers.py new file mode 100644 index 0000000..b7d91a4 --- /dev/null +++ b/ecommerce/customers/serializers.py @@ -0,0 +1,52 @@ +from rest_framework import serializers +from customers.models import Customer, Country, City, Address + + +class CustomerSerializer(serializers.ModelSerializer): + """ + Customer Serializer + """ + class Meta: + model = Customer + fields = ["first_name", "last_name", "email"] + + +class CountrySerializer(serializers.ModelSerializer): + """ + Country Serializer + """ + class Meta: + model = Country + fields = ["name"] + + +class CitySerializer(serializers.ModelSerializer): + """ + City Serializer + """ + class Meta: + model = City + fields = ["name", "country"] + + +class AddressSerializer(serializers.ModelSerializer): + """ + Address Serializer + """ + class Meta: + model = Address + fields = ["customer", "name", "full_name", "line1", "line2", "phone", "district", "zipcode", "city", + "is_default"] + + +class AddressDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Address Serializer + """ + customer = CustomerSerializer() + city = CitySerializer() + + class Meta: + model = Address + fields = ["customer", "name", "full_name", "line1", "line2", "phone", "district", "zipcode", "city", + "is_default"] diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index 91ea44a..a06d0c0 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -1,3 +1,31 @@ -from django.shortcuts import render +from rest_framework import viewsets -# Create your views here. +from core.mixins import DetailedViewSetMixin +# from products.filters import ProductFilter +from customers.models import Customer +from customers.serializers import * + + +class CustomerViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Customer.objects.all() + serializer_class = CustomerSerializer + # filterset_class = ProductFilter + + +class CountryViewSet(viewsets.ModelViewSet): + queryset = Country.objects.all() + serializer_class = CountrySerializer + + +class CityViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + + +class AddressViewSet(viewsets.ModelViewSet): + queryset = Address.objects.all() + serializer_class = AddressDetailedSerializer + serializer_action_classes = { + "detailed_list": AddressDetailedSerializer, + "detailed": AddressDetailedSerializer, + } diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 3d9479a..9501224 100644 --- a/ecommerce/ecommerce/urls.py +++ b/ecommerce/ecommerce/urls.py @@ -16,11 +16,24 @@ from django.contrib import admin from django.urls import path, include +from baskets.views import BasketViewSet, BasketItemViewSet from ecommerce.router import router from products.views import ProductViewSet, CategoryViewSet +from customers.views import * +from orders.views import * router.register("products", ProductViewSet) router.register("categories", CategoryViewSet) +router.register("baskets", BasketViewSet) +router.register("basket-items", BasketItemViewSet) +router.register("customers", CustomerViewSet) +router.register("countries", CountryViewSet) +router.register("cities", CityViewSet) +router.register("addresses", AddressViewSet) +router.register("orders", OrderViewSet) +router.register("billing-addresses", BillingAddressViewSet) +router.register("shipping-addresses", ShippingAddressViewSet) +router.register("order-bank-accounts", OrderBankAccountViewSet) urlpatterns = [ path("api/", include(router.urls)), diff --git a/ecommerce/orders/managers.py b/ecommerce/orders/managers.py new file mode 100644 index 0000000..1803210 --- /dev/null +++ b/ecommerce/orders/managers.py @@ -0,0 +1,15 @@ +from django.db import models + + +class ProductQuerySet(models.QuerySet): + def banner_products(self): + return self.filter(stock__quantity__gte=10, price__amount__lt=100) + + def has_stock(self): + return self.filter(stock__quantity__gt=0) + + def action_detailed_list(self): + return self.prefetch_related("categories") + + def action_detailed(self): + return self.prefetch_related("categories") \ No newline at end of file diff --git a/ecommerce/orders/migrations/0001_initial.py b/ecommerce/orders/migrations/0001_initial.py index ebd8d39..f2648ce 100644 --- a/ecommerce/orders/migrations/0001_initial.py +++ b/ecommerce/orders/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.9 on 2021-12-04 00:15 +# Generated by Django 3.2.9 on 2021-12-08 12:44 import core.utils from django.conf import settings @@ -11,9 +11,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('customers', '0004_alter_address_district'), - ('baskets', '0001_initial'), + ('customers', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('baskets', '0001_initial'), ] operations = [ @@ -23,12 +23,12 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('full_name', models.CharField(blank=True, max_length=255, verbose_name='Full Name')), + ('full_name', models.CharField(max_length=255, verbose_name='Full Name')), ('line_1', models.CharField(max_length=255, verbose_name='Address Line 1')), - ('line_2', models.CharField(blank=True, max_length=255, verbose_name='Address Line 2')), + ('line_2', models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2')), ('phone', models.CharField(max_length=20, validators=[core.utils.PhoneNumberValidator()], verbose_name='Phone Number')), ('district', models.CharField(max_length=255, verbose_name='District')), - ('zipcode', models.CharField(blank=True, max_length=20, verbose_name='Zip Code')), + ('zipcode', models.CharField(max_length=20, verbose_name='Zip Code')), ('city', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='customers.city', verbose_name='City')), ], options={ @@ -59,9 +59,9 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('full_name', models.CharField(blank=True, max_length=255, verbose_name='Full Name')), + ('full_name', models.CharField(max_length=255, verbose_name='Full Name')), ('line_1', models.CharField(max_length=255, verbose_name='Address Line 1')), - ('line_2', models.CharField(blank=True, max_length=255, verbose_name='Address Line 2')), + ('line_2', models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2')), ('phone', models.CharField(max_length=20, validators=[core.utils.PhoneNumberValidator()], verbose_name='Phone Number')), ('district', models.CharField(max_length=255, verbose_name='District')), ('zipcode', models.CharField(blank=True, max_length=20, verbose_name='Zip Code')), diff --git a/ecommerce/orders/migrations/0002_auto_20211205_0953.py b/ecommerce/orders/migrations/0002_auto_20211205_0953.py deleted file mode 100644 index 81fd53b..0000000 --- a/ecommerce/orders/migrations/0002_auto_20211205_0953.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-05 06:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orders', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='billingaddress', - name='full_name', - field=models.CharField(max_length=255, verbose_name='Full Name'), - ), - migrations.AlterField( - model_name='billingaddress', - name='line_2', - field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2'), - ), - migrations.AlterField( - model_name='billingaddress', - name='zipcode', - field=models.CharField(max_length=20, verbose_name='Zip Code'), - ), - migrations.AlterField( - model_name='shippingaddress', - name='full_name', - field=models.CharField(max_length=255, verbose_name='Full Name'), - ), - migrations.AlterField( - model_name='shippingaddress', - name='line_2', - field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Address Line 2'), - ), - ] diff --git a/ecommerce/orders/serializers.py b/ecommerce/orders/serializers.py new file mode 100644 index 0000000..5f78398 --- /dev/null +++ b/ecommerce/orders/serializers.py @@ -0,0 +1,89 @@ +from django.db.transaction import atomic +from rest_framework import serializers + +from baskets.serializers import BasketSerializer +from customers.serializers import CitySerializer, CustomerSerializer +from orders.models import * + + +class BillingAddressSerializer(serializers.ModelSerializer): + """ + Billing Address Serializer + """ + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class ShippingAddressSerializer(serializers.ModelSerializer): + """ + Shipping Address Serializer + """ + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class OrderSerializer(serializers.ModelSerializer): + """ + Order Serializer + """ + class Meta: + model = Order + fields = ["customer", "basket", "status", "billing_address", "shipping_address", "total_price"] + + +class OrderBankAccountSerializer(serializers.ModelSerializer): + """ + Order Bank Account Serializer + """ + class Meta: + model = OrderBankAccount + fields = ["name", "iban", "bank_name", "order"] + + +class BillingAddressDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Billing Address Serializer + """ + city = CitySerializer + + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class ShippingAddressDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Shipping Address Serializer + """ + city = CitySerializer + + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class OrderDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Order Serializer + """ + customer = CustomerSerializer + basket = BasketSerializer + billing_address = BillingAddressSerializer + shipping_address = ShippingAddressSerializer + + class Meta: + model = Order + fields = ["customer", "basket", "status", "billing_address", "shipping_address", "total_price"] + + +class OrderBankAccountDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Order Bank Account Serializer + """ + order = OrderSerializer + + class Meta: + model = OrderBankAccount + fields = ["name", "iban", "bank_name", "order"] \ No newline at end of file diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index 91ea44a..5c57f55 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,3 +1,46 @@ -from django.shortcuts import render +from rest_framework import viewsets -# Create your views here. +from core.mixins import DetailedViewSetMixin +# from orders.filters import ProductFilter +from orders.models import Order +from orders.serializers import * + + +class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Order.objects.all() + serializer_class = OrderSerializer + # filterset_class = ProductFilter + serializer_action_classes = { + "detailed_list": OrderDetailedSerializer, + "detailed": OrderDetailedSerializer, + } + + +class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = BillingAddress.objects.all() + serializer_class = BillingAddressSerializer + # filterset_class = ProductFilter + serializer_action_classes = { + "detailed_list": BillingAddressDetailedSerializer, + "detailed": BillingAddressDetailedSerializer, + } + + +class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = ShippingAddress.objects.all() + serializer_class = ShippingAddressSerializer + # filterset_class = ProductFilter + serializer_action_classes = { + "detailed_list": ShippingAddressDetailedSerializer, + "detailed": ShippingAddressDetailedSerializer, + } + + +class OrderBankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = OrderBankAccount.objects.all() + serializer_class = OrderBankAccountSerializer + # filterset_class = ProductFilter + serializer_action_classes = { + "detailed_list": OrderBankAccountDetailedSerializer, + "detailed": OrderBankAccountDetailedSerializer, + } diff --git a/ecommerce/payments/migrations/0001_initial.py b/ecommerce/payments/migrations/0001_initial.py index debba57..d904166 100644 --- a/ecommerce/payments/migrations/0001_initial.py +++ b/ecommerce/payments/migrations/0001_initial.py @@ -1,8 +1,8 @@ -# Generated by Django 3.2.9 on 2021-12-03 21:04 +# Generated by Django 3.2.9 on 2021-12-08 12:44 +import core.utils from django.db import migrations, models import django.db.models.deletion -import payments.models class Migration(migrations.Migration): @@ -33,7 +33,7 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), ('name', models.CharField(max_length=100, verbose_name='Bank Account Name')), - ('iban', models.CharField(max_length=100, validators=[payments.models.IBANValidator()], verbose_name='IBAN')), + ('iban', models.CharField(max_length=100, validators=[core.utils.IBANValidator()], verbose_name='IBAN')), ('bank', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='payments.bank', verbose_name='Bank Name')), ], options={ diff --git a/ecommerce/products/filters.py b/ecommerce/products/filters.py index 1ab7578..3f2ce66 100644 --- a/ecommerce/products/filters.py +++ b/ecommerce/products/filters.py @@ -14,4 +14,5 @@ class Meta: def filter_name(self, qs, name, value): replaced_value = value.replace("Ş", "ş") + breakpoint() return qs.filter(Q(name__icontains=replaced_value) | Q(name__icontains=value)) diff --git a/ecommerce/products/managers.py b/ecommerce/products/managers.py index c3b1a99..1803210 100644 --- a/ecommerce/products/managers.py +++ b/ecommerce/products/managers.py @@ -12,4 +12,4 @@ def action_detailed_list(self): return self.prefetch_related("categories") def action_detailed(self): - return self.prefetch_related("categories") + return self.prefetch_related("categories") \ No newline at end of file diff --git a/ecommerce/products/migrations/0001_initial.py b/ecommerce/products/migrations/0001_initial.py index 128d979..4667411 100644 --- a/ecommerce/products/migrations/0001_initial.py +++ b/ecommerce/products/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 3.2.9 on 2021-11-28 10:29 +# Generated by Django 3.2.9 on 2021-12-08 12:44 from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -11,6 +12,19 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('name', models.CharField(max_length=255, verbose_name='Category Name')), + ], + options={ + 'verbose_name': 'category', + 'verbose_name_plural': 'categories', + }, + ), migrations.CreateModel( name='Product', fields=[ @@ -22,10 +36,39 @@ class Migration(migrations.Migration): ('description', models.TextField(max_length=2000, verbose_name='Description')), ('color', models.CharField(choices=[('red', 'Red'), ('blue', 'Blue'), ('white', 'White'), ('yellow', 'Yellow')], max_length=20, verbose_name='Color')), ('size', models.CharField(max_length=30, verbose_name='Size')), + ('categories', models.ManyToManyField(to='products.Category', verbose_name='Categories')), ], options={ 'verbose_name': 'product', 'verbose_name_plural': 'products', }, ), + migrations.CreateModel( + name='Stock', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('quantity', models.PositiveIntegerField(verbose_name='Quantity')), + ('product', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product')), + ], + options={ + 'verbose_name': 'stock', + 'verbose_name_plural': 'stocks', + }, + ), + migrations.CreateModel( + name='Price', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), + ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), + ('amount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Amount')), + ('product', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product')), + ], + options={ + 'verbose_name': 'price', + 'verbose_name_plural': 'prices', + }, + ), ] diff --git a/ecommerce/products/migrations/0002_price_stock.py b/ecommerce/products/migrations/0002_price_stock.py deleted file mode 100644 index fe839dc..0000000 --- a/ecommerce/products/migrations/0002_price_stock.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 3.2.9 on 2021-11-28 11:15 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('products', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Stock', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('quantity', models.PositiveIntegerField(verbose_name='Quantity')), - ('product', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product')), - ], - options={ - 'verbose_name': 'stock', - 'verbose_name_plural': 'stocks', - }, - ), - migrations.CreateModel( - name='Price', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('amount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Amount')), - ('product', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='products.product', verbose_name='Product')), - ], - options={ - 'verbose_name': 'price', - 'verbose_name_plural': 'prices', - }, - ), - ] diff --git a/ecommerce/products/migrations/0003_auto_20211203_1919.py b/ecommerce/products/migrations/0003_auto_20211203_1919.py deleted file mode 100644 index 0fad1bb..0000000 --- a/ecommerce/products/migrations/0003_auto_20211203_1919.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-03 16:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('products', '0002_price_stock'), - ] - - operations = [ - migrations.CreateModel( - name='Category', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')), - ('modified_at', models.DateTimeField(auto_now=True, verbose_name='Modified at')), - ('name', models.CharField(max_length=255, verbose_name='Category Name')), - ], - options={ - 'verbose_name': 'category', - 'verbose_name_plural': 'categories', - }, - ), - migrations.AddField( - model_name='product', - name='categories', - field=models.ManyToManyField(to='products.Category', verbose_name='Category Name'), - ), - ] diff --git a/ecommerce/products/migrations/0004_alter_product_categories.py b/ecommerce/products/migrations/0004_alter_product_categories.py deleted file mode 100644 index 9e20adb..0000000 --- a/ecommerce/products/migrations/0004_alter_product_categories.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.9 on 2021-12-05 06:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('products', '0003_auto_20211203_1919'), - ] - - operations = [ - migrations.AlterField( - model_name='product', - name='categories', - field=models.ManyToManyField(to='products.Category', verbose_name='Categories'), - ), - ] diff --git a/ecommerce/products/serializers.py b/ecommerce/products/serializers.py index a7eb006..c945f8f 100644 --- a/ecommerce/products/serializers.py +++ b/ecommerce/products/serializers.py @@ -36,5 +36,3 @@ def create(self, validated_data): product.categories.add(*serializer.instance) return product - - From 6f71fccae8e39831d7281b4bc2197f5d1bec23df Mon Sep 17 00:00:00 2001 From: "ahmetbahadircol@gmail.com" Date: Sat, 11 Dec 2021 08:31:29 +0300 Subject: [PATCH 2/2] Added serializer, filter and views files to missing apps. Pagination API is implemented. --- ecommerce/baskets/filters.py | 5 ++- ecommerce/ecommerce/settings.py | 4 +- ecommerce/ecommerce/urls.py | 4 ++ ecommerce/orders/filters.py | 66 +++++++++++++++++++++++++++++++ ecommerce/orders/serializers.py | 22 ++++++++++- ecommerce/orders/views.py | 20 +++++++--- ecommerce/payments/filters.py | 25 ++++++++++++ ecommerce/payments/serializers.py | 33 ++++++++++++++++ ecommerce/payments/views.py | 22 ++++++++++- 9 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 ecommerce/orders/filters.py create mode 100644 ecommerce/payments/filters.py create mode 100644 ecommerce/payments/serializers.py diff --git a/ecommerce/baskets/filters.py b/ecommerce/baskets/filters.py index 06d9e91..8a1457f 100644 --- a/ecommerce/baskets/filters.py +++ b/ecommerce/baskets/filters.py @@ -12,8 +12,9 @@ class Meta: model = Basket fields = ("customer", "status") - def filter_name(self, name, qs, value): - return qs.filter(Q(customer__first_name__icontains=replaced_value) | Q(customer__first_name__icontains=value)) + @staticmethod + def filter_name(self, qs, name, value): + return qs.filter(customer__first_name__icontains=value) class BasketItemFilter(filters.FilterSet): diff --git a/ecommerce/ecommerce/settings.py b/ecommerce/ecommerce/settings.py index 898a8ee..ac3bdae 100644 --- a/ecommerce/ecommerce/settings.py +++ b/ecommerce/ecommerce/settings.py @@ -54,7 +54,9 @@ ] REST_FRAMEWORK = { - 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] + 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'], + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 100 } MIDDLEWARE = [ diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 9501224..c401f4f 100644 --- a/ecommerce/ecommerce/urls.py +++ b/ecommerce/ecommerce/urls.py @@ -18,6 +18,7 @@ from baskets.views import BasketViewSet, BasketItemViewSet from ecommerce.router import router +from payments.views import BankViewSet, BankAccountViewSet from products.views import ProductViewSet, CategoryViewSet from customers.views import * from orders.views import * @@ -31,9 +32,12 @@ router.register("cities", CityViewSet) router.register("addresses", AddressViewSet) router.register("orders", OrderViewSet) +router.register("order-items", OrderItemViewSet) router.register("billing-addresses", BillingAddressViewSet) router.register("shipping-addresses", ShippingAddressViewSet) router.register("order-bank-accounts", OrderBankAccountViewSet) +router.register("banks", BankViewSet) +router.register("bank-accounts", BankAccountViewSet) urlpatterns = [ path("api/", include(router.urls)), diff --git a/ecommerce/orders/filters.py b/ecommerce/orders/filters.py new file mode 100644 index 0000000..80e40a0 --- /dev/null +++ b/ecommerce/orders/filters.py @@ -0,0 +1,66 @@ +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ +from orders.models import * + + +class BillingAddressFilter(filters.FilterSet): + """ + Billing Address Filter + """ + full_name = filters.CharFilter(label=_("Full Name"), lookup_expr="icontains") + line_1 = filters.CharFilter(label=_("Address Line 1"), lookup_expr="icontains") + line_2 = filters.CharFilter(label=_("Address Line 2"), lookup_expr="icontains") + district = filters.CharFilter(label=_("District"), lookup_expr="icontains") + city = filters.CharFilter(label=_("City"), lookup_expr="icontains") + + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", + "phone", "district", "zipcode", "city") + + +class ShippingAddressFilter(filters.FilterSet): + """ + Billing Address Filter + """ + full_name = filters.CharFilter(label=_("Full Name"), lookup_expr="icontains") + line_1 = filters.CharFilter(label=_("Address Line 1"), lookup_expr="icontains") + line_2 = filters.CharFilter(label=_("Address Line 2"), lookup_expr="icontains") + district = filters.CharFilter(label=_("District"), lookup_expr="icontains") + city = filters.CharFilter(label=_("City"), lookup_expr="icontains") + + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", + "phone", "district", "zipcode", "city") + + +class OrderBankAccountFilter(filters.FilterSet): + """ + Order Bank Account Filter + """ + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + iban = filters.CharFilter(label=_("IBAN"), lookup_expr="icontains") + bank_name = filters.CharFilter(label=_("Bank Name"), lookup_expr="icontains") + + class Meta: + model = OrderBankAccount + fields = ["name", "iban", "bank_name", "order"] + + +class OrderFilter(filters.FilterSet): + """ + Order Filter + """ + class Meta: + model = Order + fields = ["customer", "basket", "status"] + + +class OrderItemFilter(filters.FilterSet): + """ + Order Item Filter + """ + class Meta: + model = OrderItem + fields = ["order", "product", "price"] diff --git a/ecommerce/orders/serializers.py b/ecommerce/orders/serializers.py index 5f78398..e398ef5 100644 --- a/ecommerce/orders/serializers.py +++ b/ecommerce/orders/serializers.py @@ -42,6 +42,15 @@ class Meta: fields = ["name", "iban", "bank_name", "order"] +class OrderItemSerializer(serializers.ModelSerializer): + """ + Order Item Serializer + """ + class Meta: + model = OrderItem + fields = ["order", "product", "price"] + + class BillingAddressDetailedSerializer(serializers.ModelSerializer): """ Detailed Billing Address Serializer @@ -86,4 +95,15 @@ class OrderBankAccountDetailedSerializer(serializers.ModelSerializer): class Meta: model = OrderBankAccount - fields = ["name", "iban", "bank_name", "order"] \ No newline at end of file + fields = ["name", "iban", "bank_name", "order"] + + +class OrderItemDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Order Item Serializer + """ + order = OrderSerializer + + class Meta: + model = OrderItem + fields = ["order", "product", "price"] diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index 5c57f55..fd1186c 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,7 +1,7 @@ from rest_framework import viewsets from core.mixins import DetailedViewSetMixin -# from orders.filters import ProductFilter +from orders.filters import * from orders.models import Order from orders.serializers import * @@ -9,7 +9,7 @@ class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): queryset = Order.objects.all() serializer_class = OrderSerializer - # filterset_class = ProductFilter + filterset_class = OrderFilter serializer_action_classes = { "detailed_list": OrderDetailedSerializer, "detailed": OrderDetailedSerializer, @@ -19,7 +19,7 @@ class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): queryset = BillingAddress.objects.all() serializer_class = BillingAddressSerializer - # filterset_class = ProductFilter + filterset_class = BillingAddressFilter serializer_action_classes = { "detailed_list": BillingAddressDetailedSerializer, "detailed": BillingAddressDetailedSerializer, @@ -29,7 +29,7 @@ class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): queryset = ShippingAddress.objects.all() serializer_class = ShippingAddressSerializer - # filterset_class = ProductFilter + filterset_class = ShippingAddressFilter serializer_action_classes = { "detailed_list": ShippingAddressDetailedSerializer, "detailed": ShippingAddressDetailedSerializer, @@ -39,8 +39,18 @@ class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class OrderBankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): queryset = OrderBankAccount.objects.all() serializer_class = OrderBankAccountSerializer - # filterset_class = ProductFilter + filterset_class = OrderBankAccountFilter serializer_action_classes = { "detailed_list": OrderBankAccountDetailedSerializer, "detailed": OrderBankAccountDetailedSerializer, } + + +class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = OrderItem.objects.all() + serializer_class = OrderItemSerializer + filterset_class = OrderItemFilter + serializer_action_classes = { + "detailed_list": OrderItemDetailedSerializer, + "detailed": OrderItemDetailedSerializer, + } diff --git a/ecommerce/payments/filters.py b/ecommerce/payments/filters.py new file mode 100644 index 0000000..f827bf2 --- /dev/null +++ b/ecommerce/payments/filters.py @@ -0,0 +1,25 @@ +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ +from payments.models import * + + +class BankFilter(filters.FilterSet): + """ + Bank Filter + """ + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = Bank + fields = ["name"] + + +class BankAccountFilter(filters.FilterSet): + """ + Bank Account Filter + """ + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = BankAccount + fields = ["bank", "name", "iban"] diff --git a/ecommerce/payments/serializers.py b/ecommerce/payments/serializers.py new file mode 100644 index 0000000..a214db1 --- /dev/null +++ b/ecommerce/payments/serializers.py @@ -0,0 +1,33 @@ +from rest_framework import serializers + +from payments.models import Bank, BankAccount + + +class BankSerializer(serializers.ModelSerializer): + """ + Bank Serializer + """ + class Meta: + model = Bank + fields = ["name"] + + +class BankAccountSerializer(serializers.ModelSerializer): + """ + Bank Account Serializer + """ + class Meta: + model = BankAccount + fields = ["bank", "name", "iban"] + + +class BankAccountDetailedSerializer(serializers.ModelSerializer): + """ + Detailed Bank Account Serializer + """ + bank = BankSerializer + + class Meta: + model = BankAccount + fields = ["bank", "name", "iban"] + diff --git a/ecommerce/payments/views.py b/ecommerce/payments/views.py index 91ea44a..d9a42db 100644 --- a/ecommerce/payments/views.py +++ b/ecommerce/payments/views.py @@ -1,3 +1,21 @@ -from django.shortcuts import render +from rest_framework import viewsets +from core.mixins import DetailedViewSetMixin +from payments.filters import BankFilter, BankAccountFilter +from payments.models import Bank, BankAccount +from payments.serializers import BankSerializer, BankAccountSerializer -# Create your views here. + +class BankViewSet(viewsets.ModelViewSet): + queryset = Bank.objects.all() + serializer_class = BankSerializer + filterset_class = BankFilter + + +class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = BankAccount.objects.all() + serializer_class = BankAccountSerializer + filterset_class = BankAccountFilter + serializer_action_classes = { + "detailed_list": "BankAccountDetailedSerializer", + "detailed": "BankAccountDetailedSerializer" + }