diff --git a/ecommerce/baskets/filters.py b/ecommerce/baskets/filters.py new file mode 100644 index 0000000..e668547 --- /dev/null +++ b/ecommerce/baskets/filters.py @@ -0,0 +1,19 @@ +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): + status = filters.CharFilter(label=_("Status"), lookup_expr="icontains") + + class Meta: + model = Basket + fields = ("customer", "status") + + +class BasketItemFilter(filters.FilterSet): + + class Meta: + model = BasketItem + fields = ("basket", "product", "quantity", "price") diff --git a/ecommerce/baskets/migrations/0001_initial.py b/ecommerce/baskets/migrations/0001_initial.py index 79a58d7..2b443b8 100644 --- a/ecommerce/baskets/migrations/0001_initial.py +++ b/ecommerce/baskets/migrations/0001_initial.py @@ -1,6 +1,5 @@ -# Generated by Django 3.2.9 on 2021-12-03 17:37 +# Generated by Django 3.2.9 on 2021-12-08 13:35 -from django.conf import settings from django.db import migrations, models import django.db.models.deletion @@ -10,8 +9,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('products', '0003_auto_20211203_1919'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('products', '0001_initial'), ] operations = [ @@ -21,8 +19,7 @@ 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')), ], options={ 'verbose_name': 'Basket', @@ -37,8 +34,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/migrations/0002_basket_customer.py b/ecommerce/baskets/migrations/0002_basket_customer.py new file mode 100644 index 0000000..8affa63 --- /dev/null +++ b/ecommerce/baskets/migrations/0002_basket_customer.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.9 on 2021-12-08 13:35 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('baskets', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + 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'), + ), + ] diff --git a/ecommerce/baskets/serializers.py b/ecommerce/baskets/serializers.py new file mode 100644 index 0000000..eed56d6 --- /dev/null +++ b/ecommerce/baskets/serializers.py @@ -0,0 +1,36 @@ +from rest_framework import serializers + +from baskets.models import Basket, BasketItem +from customers.serializers import CustomerSerializer +from products.serializers import ProductDetailedSerializer + + +class BasketSerializer(serializers.ModelSerializer): + + class Meta: + model = Basket + fields = ("customer", "status") + + +class BasketDetailedSerializer(serializers.ModelSerializer): + customer = CustomerSerializer() + + class Meta: + model = Basket + fields = ("customer", "status") + + +class BasketItemSerializer(serializers.ModelSerializer): + + class Meta: + model = BasketItem + fields = ("basket", "product", "quantity", "price") + + +class BasketItemDetailedSerializer(serializers.ModelSerializer): + basket = BasketDetailedSerializer() + product = ProductDetailedSerializer() + + class Meta: + model = BasketItem + fields = ("basket", "product", "quantity", "price") diff --git a/ecommerce/baskets/views.py b/ecommerce/baskets/views.py index 91ea44a..0f3b781 100644 --- a/ecommerce/baskets/views.py +++ b/ecommerce/baskets/views.py @@ -1,3 +1,27 @@ -from django.shortcuts import render +from rest_framework import viewsets -# Create your views here. +from core.mixins import DetailedViewSetMixin +from baskets.filters import BasketFilter, BasketItemFilter +from baskets.models import Basket, BasketItem +from baskets.serializers import BasketSerializer, BasketDetailedSerializer, \ + BasketItemSerializer, BasketItemDetailedSerializer + + +class BasketViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Basket.objects.all() + serializer_class = BasketSerializer + filterset_class = BasketFilter + serializer_action_classes = { + "detailed_list": BasketDetailedSerializer, + "detailed": BasketDetailedSerializer, + } + + +class BasketItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = BasketItem.objects.all() + serializer_class = BasketItemSerializer + filterset_class = BasketItemFilter + serializer_action_classes = { + "detailed_list": BasketItemDetailedSerializer, + "detailed": BasketItemDetailedSerializer, + } diff --git a/ecommerce/customers/filters.py b/ecommerce/customers/filters.py new file mode 100644 index 0000000..aac0395 --- /dev/null +++ b/ecommerce/customers/filters.py @@ -0,0 +1,38 @@ +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework as filters + +from customers.models import Customer, City, Country, Address + + +class CustomerFilter(filters.FilterSet): + first_name = filters.CharFilter(label=_("First Name"), lookup_expr="icontains") + last_name = filters.CharFilter(label=_("Last Name"), lookup_expr="icontains") + email = filters.CharFilter(label=_("Email"), lookup_expr="icontains") + + class Meta: + model = Customer + fields = ("first_name", "last_name", "email") + + +class CityFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = City + fields = ("name", "country") + + +class CountryFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = Country + fields = ("name",) + + +class AddressFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = Address + fields = ("name", "full_name", "phone", "district", "zipcode", "customer", "city") diff --git a/ecommerce/customers/migrations/0001_initial.py b/ecommerce/customers/migrations/0001_initial.py index a691fbb..39ec9f3 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 13:35 +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..7be6bb8 --- /dev/null +++ b/ecommerce/customers/serializers.py @@ -0,0 +1,54 @@ +from rest_framework import serializers + +from customers.models import City, Country, Customer, Address + + +class CountrySerializer(serializers.ModelSerializer): + + class Meta: + model = Country + fields = ("name", ) + + +class CitySerializer(serializers.ModelSerializer): + + class Meta: + model = City + fields = ("name", "country") + + +class CityDetailedSerializer(serializers.ModelSerializer): + country = CountrySerializer() + + class Meta: + model = City + fields = ("name", "country") + + +class CustomerSerializer(serializers.ModelSerializer): + + class Meta: + model = Customer + fields = ("first_name", "last_name", "email", "is_staff", "is_active", "date_joined") + + +class AddressSerializer(serializers.ModelSerializer): + + class Meta: + model = Address + fields = ("customer", "name", "full_name", "line_1", "line_2", "phone", "district", + "zipcode", "city", "is_default") + + +class AddressDetailedSerializer(serializers.ModelSerializer): + customer = CustomerSerializer() + city = CityDetailedSerializer() + + class Meta: + model = Address + fields = ("customer", "name", "full_name", "line_1", "line_2", "phone", "district", + "zipcode", "city", "is_default") + + + + diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index 91ea44a..3042167 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -1,3 +1,40 @@ -from django.shortcuts import render +from rest_framework import viewsets + +from core.mixins import DetailedViewSetMixin +from customers.filters import CustomerFilter, CityFilter, CountryFilter, AddressFilter +from customers.models import Country, City, Customer, Address +from customers.serializers import CountrySerializer, CitySerializer, CityDetailedSerializer, \ + CustomerSerializer, AddressSerializer, AddressDetailedSerializer + + +class CountryViewSet(viewsets.ModelViewSet): + queryset = Country.objects.all() + filterset_class = CountryFilter + serializer_class = CountrySerializer + + +class CityViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + filterset_class = CityFilter + serializer_action_classes = { + "detailed_list": CityDetailedSerializer, + "detailed": CityDetailedSerializer, + } + + +class CustomerViewSet(viewsets.ModelViewSet): + queryset = Customer.objects.all() + filterset_class = CustomerFilter + serializer_class = CustomerSerializer + + +class AddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Address.objects.all() + serializer_class = AddressSerializer + filterset_class = AddressFilter + serializer_action_classes = { + "detailed_list": AddressDetailedSerializer, + "detailed": AddressDetailedSerializer, + } -# Create your views here. diff --git a/ecommerce/ecommerce/settings.py b/ecommerce/ecommerce/settings.py index 898a8ee..7d068a1 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.PageNumberPagination', + 'PAGE_SIZE': 5 } MIDDLEWARE = [ diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 3d9479a..996d4dd 100644 --- a/ecommerce/ecommerce/urls.py +++ b/ecommerce/ecommerce/urls.py @@ -17,10 +17,34 @@ from django.urls import path, include from ecommerce.router import router -from products.views import ProductViewSet, CategoryViewSet +from products.views import ProductViewSet, CategoryViewSet, StockViewSet, PriceViewSet +from payments.views import BankViewSet, BankAccountViewSet +from orders.views import BillingAddressViewSet, ShippingAddressViewSet, OrderBankAccountViewSet, \ + OrderViewSet, OrderItemViewSet +from customers.views import CountryViewSet, CityViewSet, CustomerViewSet, AddressViewSet +from baskets.views import BasketViewSet, BasketItemViewSet router.register("products", ProductViewSet) router.register("categories", CategoryViewSet) +router.register("stocks", StockViewSet) +router.register("prices", PriceViewSet) + +router.register("banks", BankViewSet) +router.register("bank_accounts", BankAccountViewSet) + +router.register("billing_addresses", BillingAddressViewSet) +router.register("shipping_addresses", ShippingAddressViewSet) +router.register("order_bank_accounts", OrderBankAccountViewSet) +router.register("orders", OrderViewSet) +router.register("order_items", OrderItemViewSet) + +router.register("countries", CountryViewSet) +router.register("cities", CityViewSet) +router.register("customers", CustomerViewSet) +router.register("addresses", AddressViewSet) + +router.register("baskets", BasketViewSet) +router.register("basket_items", BasketItemViewSet) urlpatterns = [ path("api/", include(router.urls)), diff --git a/ecommerce/orders/filters.py b/ecommerce/orders/filters.py new file mode 100644 index 0000000..cb3bc3a --- /dev/null +++ b/ecommerce/orders/filters.py @@ -0,0 +1,56 @@ +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework as filters + +from orders.models import BillingAddress, ShippingAddress, OrderBankAccount, Order, OrderItem + + +class BillingAddressFilter(filters.FilterSet): + ful_name = filters.CharFilter(label=_("Full Name"), lookup_expr="icontains") + line1 = filters.CharFilter(label=_("Line1"), lookup_expr="icontains") + line2 = filters.CharFilter(label=_("Line2"), lookup_expr="icontains") + phone = filters.CharFilter(label=_("Phone"), lookup_expr="icontains") + district = filters.CharFilter(label=_("District"), lookup_expr="icontains") + zipcode = filters.CharFilter(label=_("Zipcode"), lookup_expr="icontains") + + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class ShippingAddressFilter(filters.FilterSet): + ful_name = filters.CharFilter(label=_("Full Name"), lookup_expr="icontains") + line1 = filters.CharFilter(label=_("Line1"), lookup_expr="icontains") + line2 = filters.CharFilter(label=_("Line2"), lookup_expr="icontains") + phone = filters.CharFilter(label=_("Phone"), lookup_expr="icontains") + district = filters.CharFilter(label=_("District"), lookup_expr="icontains") + zipcode = filters.CharFilter(label=_("Zipcode"), lookup_expr="icontains") + + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class OrderBankAccountFilter(filters.FilterSet): + 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): + status = filters.CharFilter(label=_("Status"), lookup_expr="icontains") + + class Meta: + model = Order + fields = ("customer", "basket", "status", "billing_address", "shipping_address", "total_price") + + +class OrderItemFilter(filters.FilterSet): + product = filters.CharFilter(label=_("Product"), lookup_expr="icontains") + + class Meta: + model = OrderItem + fields = ("order", "product", "price") diff --git a/ecommerce/orders/migrations/0001_initial.py b/ecommerce/orders/migrations/0001_initial.py index ebd8d39..001363d 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 13:35 import core.utils from django.conf import settings @@ -11,7 +11,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('customers', '0004_alter_address_district'), + ('customers', '0001_initial'), ('baskets', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] @@ -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..bc6bb8e --- /dev/null +++ b/ecommerce/orders/serializers.py @@ -0,0 +1,85 @@ +from rest_framework import serializers + +from baskets.serializers import BasketDetailedSerializer +from customers.serializers import CustomerSerializer, CityDetailedSerializer +from orders.models import BillingAddress, ShippingAddress, OrderBankAccount, Order, OrderItem + + +class BillingAddressSerializer(serializers.ModelSerializer): + + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class BillingAddressDetailedSerializer(serializers.ModelSerializer): + city = CityDetailedSerializer() + + class Meta: + model = BillingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class ShippingAddressSerializer(serializers.ModelSerializer): + + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class ShippingAddressDetailedSerializer(serializers.ModelSerializer): + city = CityDetailedSerializer() + + class Meta: + model = ShippingAddress + fields = ("full_name", "line_1", "line_2", "phone", "district", "zipcode", "city") + + +class OrderSerializer(serializers.ModelSerializer): + + class Meta: + model = Order + fields = ("customer", "basket", "status", "billing_address", "shipping_address", "total_price") + + +class OrderDetailedSerializer(serializers.ModelSerializer): + customer = CustomerSerializer() + basket = BasketDetailedSerializer() + billing_address = BillingAddressDetailedSerializer() + shipping_address = ShippingAddressDetailedSerializer() + + class Meta: + model = Order + fields = ("customer", "basket", "status", "billing_address", "shipping_address", "total_price") + + +class OrderBankAccountSerializer(serializers.ModelSerializer): + + class Meta: + model = OrderBankAccount + fields = ("name", "iban", "bank_name", "order") + + +class OrderBankAccountDetailedSerializer(serializers.ModelSerializer): + order = OrderDetailedSerializer() + + class Meta: + model = OrderBankAccount + fields = ("name", "iban", "bank_name", "order") + + +class OrderItemSerializer(serializers.ModelSerializer): + + class Meta: + model = OrderItem + fields = ("order", "product", "price") + + +class OrderItemDetailedSerializer(serializers.ModelSerializer): + order = OrderDetailedSerializer() + + class Meta: + model = OrderItem + fields = ("order", "product", "price") + + diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index 91ea44a..506da03 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,3 +1,61 @@ -from django.shortcuts import render +from rest_framework import viewsets + +from core.mixins import DetailedViewSetMixin +from orders.filters import BillingAddressFilter, ShippingAddressFilter, OrderBankAccountFilter, \ + OrderFilter, OrderItemFilter +from orders.models import BillingAddress, ShippingAddress, OrderBankAccount, Order, OrderItem +from orders.serializers import BillingAddressSerializer, BillingAddressDetailedSerializer, ShippingAddressSerializer, \ + ShippingAddressDetailedSerializer, OrderBankAccountSerializer, OrderBankAccountDetailedSerializer, \ + OrderSerializer, OrderDetailedSerializer, OrderItemSerializer, OrderItemDetailedSerializer + + +class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = BillingAddress.objects.all() + serializer_class = BillingAddressSerializer + filterset_class = BillingAddressFilter + serializer_action_classes = { + "detailed_list": BillingAddressDetailedSerializer, + "detailed": BillingAddressDetailedSerializer, + } + + +class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = ShippingAddress.objects.all() + serializer_class = ShippingAddressSerializer + filterset_class = ShippingAddressFilter + serializer_action_classes = { + "detailed_list": ShippingAddressDetailedSerializer, + "detailed": ShippingAddressDetailedSerializer, + } + + +class OrderBankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = OrderBankAccount.objects.all() + serializer_class = OrderBankAccountSerializer + filterset_class = OrderBankAccountFilter + serializer_action_classes = { + "detailed_list": OrderBankAccountDetailedSerializer, + "detailed": OrderBankAccountDetailedSerializer, + } + + +class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Order.objects.all() + serializer_class = OrderSerializer + filterset_class = OrderFilter + serializer_action_classes = { + "detailed_list": OrderDetailedSerializer, + "detailed": OrderDetailedSerializer, + } + + +class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = OrderItem.objects.all() + serializer_class = OrderItemSerializer + filterset_class = OrderItemFilter + serializer_action_classes = { + "detailed_list": OrderItemDetailedSerializer, + "detailed": OrderItemDetailedSerializer, + } + -# Create your views here. diff --git a/ecommerce/payments/filters.py b/ecommerce/payments/filters.py new file mode 100644 index 0000000..4896727 --- /dev/null +++ b/ecommerce/payments/filters.py @@ -0,0 +1,21 @@ +from django.utils.translation import gettext_lazy as _ +from django_filters import rest_framework as filters + +from payments.models import Bank, BankAccount + + +class BankFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = Bank + fields = ("name", ) + + +class BankAccountFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + iban = filters.CharFilter(label=_("Iban"), lookup_expr="icontains") + + class Meta: + model = BankAccount + fields = ("bank", "name", "iban") diff --git a/ecommerce/payments/migrations/0001_initial.py b/ecommerce/payments/migrations/0001_initial.py index debba57..881afe1 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 13:35 +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/payments/serializers.py b/ecommerce/payments/serializers.py new file mode 100644 index 0000000..7f7020a --- /dev/null +++ b/ecommerce/payments/serializers.py @@ -0,0 +1,25 @@ +from rest_framework import serializers + +from payments.models import Bank, BankAccount + + +class BankSerializer(serializers.ModelSerializer): + + class Meta: + model = Bank + fields = ( "name", ) + + +class BankAccountSerializer(serializers.ModelSerializer): + + class Meta: + model = BankAccount + fields = ("bank", "name", "iban") + + +class BankAccountDetailedSerializer(serializers.ModelSerializer): + bank = BankSerializer() + + class Meta: + model = BankAccount + fields = ("bank", "name", "iban") diff --git a/ecommerce/payments/views.py b/ecommerce/payments/views.py index 91ea44a..eb12fc5 100644 --- a/ecommerce/payments/views.py +++ b/ecommerce/payments/views.py @@ -1,3 +1,23 @@ -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, BankAccountDetailedSerializer + + +class BankViewSet(viewsets.ModelViewSet): + queryset = Bank.objects.all() + filterset_class = BankFilter + serializer_class = BankSerializer + + +class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = BankAccount.objects.all() + serializer_class = BankAccountSerializer + filterset_class = BankAccountFilter + serializer_action_classes = { + "detailed_list": BankAccountDetailedSerializer, + "detailed": BankAccountDetailedSerializer, + } -# Create your views here. diff --git a/ecommerce/products/filters.py b/ecommerce/products/filters.py index 1ab7578..424df01 100644 --- a/ecommerce/products/filters.py +++ b/ecommerce/products/filters.py @@ -2,7 +2,15 @@ from django_filters import rest_framework as filters from django.utils.translation import gettext_lazy as _ -from products.models import Product +from products.models import Product, Category, Stock, Price + + +class CategoryFilter(filters.FilterSet): + name = filters.CharFilter(label=_("Name"), lookup_expr="icontains") + + class Meta: + model = Category + fields = ("name",) class ProductFilter(filters.FilterSet): @@ -10,8 +18,20 @@ class ProductFilter(filters.FilterSet): class Meta: model = Product - fields = ("size", "color", "name") + fields = ("size", "color", "name", "description", "color", "size", "categories") def filter_name(self, qs, name, value): replaced_value = value.replace("Ş", "ş") return qs.filter(Q(name__icontains=replaced_value) | Q(name__icontains=value)) + + +class StockFilter(filters.FilterSet): + class Meta: + model = Stock + fields = ("product", "quantity") + + +class PriceFilter(filters.FilterSet): + class Meta: + model = Price + fields = ("product", "amount") diff --git a/ecommerce/products/migrations/0001_initial.py b/ecommerce/products/migrations/0001_initial.py index 128d979..4fd67ec 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 13:35 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..7fb0b75 100644 --- a/ecommerce/products/serializers.py +++ b/ecommerce/products/serializers.py @@ -1,7 +1,7 @@ from django.db.transaction import atomic from rest_framework import serializers -from products.models import Product, Category +from products.models import Product, Category, Stock, Price class ProductSerializer(serializers.ModelSerializer): @@ -37,4 +37,31 @@ def create(self, validated_data): return product +class StockSerializer(serializers.ModelSerializer): + class Meta: + model = Stock + fields = ("product", "quantity") + + +class StockDetailedSerializer(serializers.ModelSerializer): + product = ProductSerializer() + + class Meta: + model = Stock + fields = ("product", "quantity") + + +class PriceSerializer(serializers.ModelSerializer): + + class Meta: + model = Price + fields = ("product", "amount") + + +class PriceDetailedSerializer(serializers.ModelSerializer): + product = ProductSerializer() + + class Meta: + model = Price + fields = ("product", "amount") diff --git a/ecommerce/products/views.py b/ecommerce/products/views.py index fdd33fd..1712f80 100644 --- a/ecommerce/products/views.py +++ b/ecommerce/products/views.py @@ -1,10 +1,11 @@ from rest_framework import viewsets from core.mixins import DetailedViewSetMixin -from products.filters import ProductFilter -from products.models import Product, Category +from products.filters import ProductFilter, CategoryFilter, StockFilter, PriceFilter +from products.models import Product, Category, Stock, Price from products.serializers import ProductSerializer, CategorySerializer, \ - ProductDetailedSerializer + ProductDetailedSerializer, StockSerializer, PriceSerializer, StockDetailedSerializer,\ + PriceDetailedSerializer class ProductViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): @@ -19,4 +20,25 @@ class ProductViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class CategoryViewSet(viewsets.ModelViewSet): queryset = Category.objects.all() + filterset_class = CategoryFilter serializer_class = CategorySerializer + + +class StockViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Stock.objects.all() + serializer_class = StockSerializer + filterset_class = StockFilter + serializer_action_classes = { + "detailed_list": StockDetailedSerializer, + "detailed": StockDetailedSerializer, + } + + +class PriceViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Price.objects.all() + serializer_class = PriceSerializer + filterset_class = PriceFilter + serializer_action_classes = { + "detailed_list": PriceDetailedSerializer, + "detailed": PriceDetailedSerializer, + }