diff --git a/ecommerce/.env.dist b/ecommerce/.env.dist index b7f48c2..6fc24e1 100644 --- a/ecommerce/.env.dist +++ b/ecommerce/.env.dist @@ -1,5 +1,5 @@ +SECRET_KEY=g)8v11ythdn-p_^4+@z23_1&x=qzp^(-#py*8v$&4bnjb&=$a% DEBUG=True -SECRET_KEY=secret_key -DATABASE_URL=psql://superuser_username:superuser_password@server_ip:server_port/db_name +DATABASE_URL=psql://bootcamp:123456@Localhost:5432/bootcampecommerce ALLOWED_HOSTS=127.0.0.1,0.0.0.0 -TIME_ZONE=Europe/Istanbul \ No newline at end of file +TIME_ZONE=Europe/Istanbul diff --git a/ecommerce/baskets/filters.py b/ecommerce/baskets/filters.py new file mode 100644 index 0000000..440146e --- /dev/null +++ b/ecommerce/baskets/filters.py @@ -0,0 +1,35 @@ +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 +from products.models import Product + + +class BasketFilter(filters.FilterSet): + """ + Basket Filter + """ + customer = filters.CharFilter(label=_("Customer"), method="filter_name") + + class Meta: + model = Basket + fields = ("customer", "status") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(customer__first_name__icontains=replaced_value) | Q(customer__first_name__icontains=value)) + +class BasketItemFilter(filters.FilterSet): + """ + Basket Item Filter + """ + product = filters.CharFilter(label=_("Product-Name"), method="filter_name") + + class Meta: + model = BasketItem + fields = ("basket", "product", "quantity", "price") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(product__name__icontains=replaced_value) | Q(product__name__icontains=value)) + diff --git a/ecommerce/baskets/serializers.py b/ecommerce/baskets/serializers.py new file mode 100644 index 0000000..6efbba1 --- /dev/null +++ b/ecommerce/baskets/serializers.py @@ -0,0 +1,38 @@ +from rest_framework import serializers +from django.db.transaction import atomic +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 = ("id", "customer", "status", "created_at", "modified_at") + + +class BasketItemSerializer(serializers.ModelSerializer): + product = ProductSerializer + + class Meta: + model = BasketItem + fields = ("id", "basket", "product", "quantity", "price") + + +class BasketItemDetailedSerializer(BasketItemSerializer): + """ + Basket Item Detailed Serializer + """ + basket = BasketSerializer(many=False) + + +class BasketDetailedSerializer(BasketSerializer): + """ + Basket Detailed Serializer + """ + customer = CustomerSerializer(many=False) + diff --git a/ecommerce/baskets/views.py b/ecommerce/baskets/views.py index 91ea44a..662091c 100644 --- a/ecommerce/baskets/views.py +++ b/ecommerce/baskets/views.py @@ -1,3 +1,26 @@ from django.shortcuts import render - +from rest_framework import viewsets +from baskets.serializers import BasketSerializer, BasketItemSerializer, BasketItemDetailedSerializer, BasketDetailedSerializer +from baskets.models import Basket, BasketItem +from core.mixins import DetailedViewSetMixin +from baskets.filters import BasketFilter, BasketItemFilter # Create your views here. + +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..4c8ce44 --- /dev/null +++ b/ecommerce/customers/filters.py @@ -0,0 +1,33 @@ +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 Address, Customer + + +class AddressFilter(filters.FilterSet): + customer = filters.CharFilter(label=_("Customer"), method="filter_name") + + class Meta: + model = Address + fields = ("customer", "name", "full_name", "phone", "zipcode", "city", + "district") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(customer__first_name__icontains=replaced_value) | Q(customer__first_name__icontains=value)) + +class CustomerFilter(filters.FilterSet): + """ + Customer Filter + Filters customers by their names + """ + first_name = filters.CharFilter(label=_("Name"), method="filter_name") + + class Meta: + model = Customer + fields = ("id", "first_name", "last_name", "email") + + def filter_name(self, qs, first_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/models.py b/ecommerce/customers/models.py index 71f79a6..44902eb 100644 --- a/ecommerce/customers/models.py +++ b/ecommerce/customers/models.py @@ -33,7 +33,6 @@ class Country(BaseAbstractModel): Country model """ name = models.CharField(max_length=255, verbose_name=_("Country")) - class Meta: verbose_name = _("country") verbose_name_plural = _("countries") diff --git a/ecommerce/customers/serializers.py b/ecommerce/customers/serializers.py new file mode 100644 index 0000000..3bfc6ce --- /dev/null +++ b/ecommerce/customers/serializers.py @@ -0,0 +1,71 @@ +from rest_framework import serializers +from customers.models import Customer, City, Country, Address +from django.db.transaction import atomic + + + +class CitySerializer(serializers.ModelSerializer): + + class Meta: + fields = ("id", "name", "country",) + model = City + +class CountrySerializer(serializers.ModelSerializer): + + class Meta: + model = Country + fields = ("id", "name", ) + +class CityDetailedSerializer(CitySerializer): + country = CountrySerializer(many= False) + + class Meta: + model = City + fields = ("id", "name", "country",) + +class CustomerSerializer(serializers.ModelSerializer): + + class Meta: + model = Customer + fields = ("id", "first_name", "last_name", "email") + +class AddressSerializer(serializers.ModelSerializer): + + class Meta: + model = Address + fields = ("id", "customer", "name", "full_name", "line_1", "line_2", + "phone", "district", "zipcode", "city") + +class AddressDetailedSerializer(AddressSerializer): + """ + Address Detailed Serializer + includes Customer and DetailedCity Serializers + """ + customer = CustomerSerializer(many=False) + city = CityDetailedSerializer(many= False) + + class Meta: + model = Address + fields = ("id", "customer", "name", "full_name", "line_1", "line_2", + "phone", "district", "zipcode", "city") + @atomic() + def create(self, validated_data): + customer = validated_data.pop("customer", None) + address = super().create(validated_data) + if customer: + serializer = CustomerSerializer(data=customer, many=False) + serializer.is_valid(raise_exception=True) + serializer.save() + address.customer.add(*serializer.instance) + + city = validated_data.pop("city", None) + address = super().create(validated_data) + + if city: + serializer = CityDetailedSerializer(data=city, many=False) + serializer.is_valid(raise_exception=True) + serializer.save() + address.city.add(*serializer.instance) + + return address + diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index 91ea44a..0dd2b99 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -1,3 +1,36 @@ from django.shortcuts import render - +from rest_framework import viewsets +from customers.serializers import CustomerSerializer, CitySerializer, CountrySerializer,\ + AddressSerializer, AddressDetailedSerializer, CityDetailedSerializer +from customers.models import Customer, City, Country, Address +from customers.filters import AddressFilter, CustomerFilter +from core.mixins import DetailedViewSetMixin # Create your views here. + +class CustomerViewSet(viewsets.ModelViewSet): + queryset = Customer.objects.all() + serializer_class = CustomerSerializer + filterset_class = CustomerFilter + +class CityViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + serializer_action_classes = { + "detailed_list": CityDetailedSerializer, + "detailed": CityDetailedSerializer + } + +class CountryViewSet(viewsets.ModelViewSet): + queryset = Country.objects.all() + serializer_class = CountrySerializer + + +class AddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Address.objects.all() + serializer_class = AddressSerializer + filterset_class = AddressFilter + serializer_action_classes = { + "detailed_list": AddressDetailedSerializer, + "detailed": AddressDetailedSerializer + } + diff --git a/ecommerce/ecommerce/settings.py b/ecommerce/ecommerce/settings.py index 898a8ee..73d484c 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': 100 } MIDDLEWARE = [ diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 3d9479a..b578f40 100644 --- a/ecommerce/ecommerce/urls.py +++ b/ecommerce/ecommerce/urls.py @@ -15,12 +15,29 @@ """ from django.contrib import admin from django.urls import path, include - from ecommerce.router import router from products.views import ProductViewSet, CategoryViewSet +from baskets.views import BasketViewSet, BasketItemViewSet +from customers.views import CustomerViewSet, CityViewSet, CountryViewSet, AddressViewSet +from payments.views import BankViewSet, BankAccountViewSet +from orders.views import BillingAddressViewSet, ShippingAddressViewSet,\ + OrderBankAccountViewSet, OrderViewSet, OrderItemViewSet router.register("products", ProductViewSet) router.register("categories", CategoryViewSet) +router.register("customers", CustomerViewSet) +router.register("cities", CityViewSet) +router.register("countries", CountryViewSet) +router.register("addresses", AddressViewSet) +router.register("baskets", BasketViewSet) +router.register("basket_items", BasketItemViewSet) +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("order_items", OrderItemViewSet) + urlpatterns = [ path("api/", include(router.urls)), diff --git a/ecommerce/orders/filters.py b/ecommerce/orders/filters.py new file mode 100644 index 0000000..b876b33 --- /dev/null +++ b/ecommerce/orders/filters.py @@ -0,0 +1,20 @@ +from django.db.models import Q +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ +from orders.models import Order, OrderItem + + + +class OrderFilter(filters.FilterSet): + """ + Order Filter + """ + customer = filters.CharFilter(label=_("Customer"), method="filter_name") + + class Meta: + model = Order + fields = ("customer", "basket", "status") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(customer__first_name__icontains=replaced_value) | Q(customer__first_name__icontains=value)) diff --git a/ecommerce/orders/serializers.py b/ecommerce/orders/serializers.py new file mode 100644 index 0000000..266231a --- /dev/null +++ b/ecommerce/orders/serializers.py @@ -0,0 +1,71 @@ +from django.db.transaction import atomic +from rest_framework import serializers +from customers.serializers import CustomerSerializer +from orders.models import Order, OrderItem, OrderBankAccount, BillingAddress, \ + ShippingAddress +from products.serializers import ProductSerializer + +class BillingAddressSerializer(serializers.ModelSerializer): + + class Meta: + model = BillingAddress + fields = ("id", "full_name", "line_1", "line_2", "phone", + "district", "zipcode", "city") + +class ShippingAddressSerializer(serializers.ModelSerializer): + + class Meta: + model = ShippingAddress + fields = ("id", "full_name", "line_1", "line_2", "phone", + "district", "zipcode", "city") + +class OrderBankAccountSerializer(serializers.ModelSerializer): + + class Meta: + model = OrderBankAccount + fields = ("id", "name", "iban", "bank_name", "order") + +class OrderSerializer(serializers.ModelSerializer): + + class Meta: + model = Order + fields = ("customer", "basket", "status", "billing_address", + "shipping_address", "total_price","created_at","modified_at") + +class OrderItemSerializer(serializers.ModelSerializer): + + class Meta: + model = OrderItem + fields = ("order", "product", "price") + +class OrderItemDetailedSerializer(serializers.ModelSerializer): + """ + Order Item Detailed Serializer + Order and Product Informations Included + """ + order = OrderSerializer(many=False) + product = ProductSerializer(many=True) + + class Meta: + model = OrderItem + fields = ("order", "product", "price") + + @atomic() + def create(self, validated_data): + order = validated_data.pop("order", None) + product = validated_data.pop("product", None) + order_item = super().create(validated_data) + + if order: + serializer = OrderSerializer(data=order, many=True) + serializer.is_valid(raise_exception=True) + serializer.save() + order_item.order.add(*serializer.instance) + + if product: + serializer = ProductSerializer(data=product, many=True) + serializer.is_valid(raise_exception=True) + serializer.save() + order_item.order.add(*serializer.instance) + + return order diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index 91ea44a..519f569 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,3 +1,35 @@ -from django.shortcuts import render +from rest_framework import viewsets -# Create your views here. +from core.mixins import DetailedViewSetMixin +from orders.filters import OrderFilter +from orders.models import BillingAddress, ShippingAddress, Order, OrderItem, OrderBankAccount +from orders.serializers import BillingAddressSerializer, ShippingAddressSerializer, \ + OrderBankAccountSerializer, OrderSerializer, OrderItemSerializer, OrderItemDetailedSerializer + + + +class BillingAddressViewSet(viewsets.ModelViewSet): + queryset = BillingAddress.objects.all() + serializer_class = BillingAddressSerializer + +class ShippingAddressViewSet(viewsets.ModelViewSet): + queryset = ShippingAddress.objects.all() + serializer_class = ShippingAddressSerializer + +class OrderBankAccountViewSet(viewsets.ModelViewSet): + queryset = OrderBankAccount.objects.all() + serializer_class = OrderBankAccountSerializer + +class OrderViewSet(viewsets.ModelViewSet): + queryset = Order.objects.all() + serializer_class = OrderSerializer + filterset_class = OrderFilter + + +class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = OrderItem.objects.all() + serializer_class = OrderItemSerializer + 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..1396b00 --- /dev/null +++ b/ecommerce/payments/filters.py @@ -0,0 +1,20 @@ +from django.db.models import Q +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ +from payments.models import Bank, BankAccount +from products.models import Product + + +class BankAccountFilter(filters.FilterSet): + """ + Basket Filter + """ + bank = filters.CharFilter(label=_("Bank"), method="filter_name") + + class Meta: + model = BankAccount + fields = ("bank", "name", "iban") + + def filter_name(self, qs, name, value): + replaced_value = value.replace("Ş", "ş") + return qs.filter(Q(bank__name__icontains=replaced_value) | Q(bank__name__icontains=value)) diff --git a/ecommerce/payments/serializers.py b/ecommerce/payments/serializers.py new file mode 100644 index 0000000..9797800 --- /dev/null +++ b/ecommerce/payments/serializers.py @@ -0,0 +1,43 @@ +from rest_framework import serializers +from django.db.transaction import atomic +from payments.models import Bank, BankAccount + +class BankSerializer(serializers.ModelSerializer): + """ + Basket Serializer + """ + + class Meta: + model = Bank + fields = ("id", "name") + + +class BankAccountSerializer(serializers.ModelSerializer): + + class Meta: + model = BankAccount + fields = ("id", "bank", "name", "iban") + + +class BankAccountDetailedSerializer(BankAccountSerializer): + """ + Bank Account Detailed Serializer + """ + bank = BankSerializer(many=False) + + class Meta: + model = BankAccount + fields = ("id", "bank", "name", "iban") + + @atomic() + def create(self, validated_data): + bank = validated_data.pop("bank", None) + bank_account = super().create(validated_data) + + if bank: + serializer = BankSerializer(data=bank, many=False) + serializer.is_valid(raise_exception=True) + serializer.save() + bank_account.bank.add(*serializer.instance) + return bank_account + diff --git a/ecommerce/payments/views.py b/ecommerce/payments/views.py index 91ea44a..64ea4d7 100644 --- a/ecommerce/payments/views.py +++ b/ecommerce/payments/views.py @@ -1,3 +1,22 @@ from django.shortcuts import render - +from rest_framework import viewsets +from payments.serializers import BankSerializer, BankAccountSerializer,BankAccountDetailedSerializer +from payments.models import Bank, BankAccount +from core.mixins import DetailedViewSetMixin +from payments.filters import BankAccountFilter # Create your views here. + +class BankViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + queryset = Bank.objects.all() + 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 + } +