From eaa856e9dacb5a532cb23b627c0a84a032703a4e Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 7 Sep 2024 21:33:49 -0500 Subject: [PATCH 1/3] feat(api): implemented create sale as api endpoint. --- requirements.txt | 1 + tienda_ilusion/don_confiao/api_views.py | 30 ++++++++++++++++++ tienda_ilusion/don_confiao/serializers.py | 17 +++++++++++ tienda_ilusion/don_confiao/tests/test_api.py | 32 ++++++++++++++++++++ tienda_ilusion/don_confiao/urls.py | 2 ++ tienda_ilusion/tienda_ilusion/settings.py | 1 + 6 files changed, 83 insertions(+) create mode 100644 tienda_ilusion/don_confiao/api_views.py create mode 100644 tienda_ilusion/don_confiao/serializers.py create mode 100644 tienda_ilusion/don_confiao/tests/test_api.py diff --git a/requirements.txt b/requirements.txt index 284d5f5..035edf6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ Django==5.0.6 +djangorestframework diff --git a/tienda_ilusion/don_confiao/api_views.py b/tienda_ilusion/don_confiao/api_views.py new file mode 100644 index 0000000..d5fc155 --- /dev/null +++ b/tienda_ilusion/don_confiao/api_views.py @@ -0,0 +1,30 @@ +from rest_framework import viewsets +from rest_framework.response import Response + +from .models import Sale, SaleLine, Customer, Product +from .serializers import SaleSerializer + + +class SaleViewSet(viewsets.ModelViewSet): + queryset = Sale.objects.all() + serializer_class = SaleSerializer + + def create(self, request): + data = request.data + customer = Customer.objects.get(pk=data['customer']) + date = data['date'] + lines = data['lines'] + sale = Sale.objects.create(customer=customer, date=date) + + for line in lines: + product = Product.objects.get(pk=line['product']) + quantity = line['quantity'] + unit_price = line['unit_price'] + SaleLine.objects.create( + sale=sale, + product=product, + quantity=quantity, + unit_price=unit_price + ) + + return Response({'message': 'Venta creada con exito'}, status=201) diff --git a/tienda_ilusion/don_confiao/serializers.py b/tienda_ilusion/don_confiao/serializers.py new file mode 100644 index 0000000..464c6f8 --- /dev/null +++ b/tienda_ilusion/don_confiao/serializers.py @@ -0,0 +1,17 @@ +from rest_framework import serializers + +from .models import Sale, SaleLine + + +class SaleLineSerializer(serializers.ModelSerializer): + class Meta: + model = SaleLine + fields = ['id', 'sale', 'product', 'unit_price', 'quantity'] + + +class SaleSerializer(serializers.ModelSerializer): + lines = SaleLineSerializer(many=True) + + class Meta: + model = Sale + fields = ['id', 'customer', 'date', 'lines'] diff --git a/tienda_ilusion/don_confiao/tests/test_api.py b/tienda_ilusion/don_confiao/tests/test_api.py new file mode 100644 index 0000000..5a9cb90 --- /dev/null +++ b/tienda_ilusion/don_confiao/tests/test_api.py @@ -0,0 +1,32 @@ +import json +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase +from ..models import Sale, Product, Customer + + +class TestAPI(APITestCase): + def setUp(self): + self.product = Product.objects.create( + name='Panela', + price=5000, + measuring_unit='UNIT' + ) + self.customer = Customer.objects.create( + name='Camilo' + ) + + def test_create_sale(self): + url = '/don_confiao/api/sales/' + data = { + 'customer': self.customer.id, + 'date': '2024-09-02', + 'lines': [ + {'product': self.product.id, 'quantity': 2, 'unit_price': 3000}, + {'product': self.product.id, 'quantity': 3, 'unit_price': 5000} + ], + } + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(Sale.objects.count(), 1) + self.assertEqual(Sale.objects.all()[0].customer.name, self.customer.name) diff --git a/tienda_ilusion/don_confiao/urls.py b/tienda_ilusion/don_confiao/urls.py index 7de794e..145c70a 100644 --- a/tienda_ilusion/don_confiao/urls.py +++ b/tienda_ilusion/don_confiao/urls.py @@ -1,6 +1,7 @@ from django.urls import path from . import views +from . import api_views app_name = 'don_confiao' urlpatterns = [ @@ -13,4 +14,5 @@ urlpatterns = [ path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"), path("cuadres", views.reconciliate_jar, name="reconciliations"), path("resumen_compra/", views.purchase_summary, name="purchase_summary"), + path('api/sales/', api_views.SaleViewSet.as_view({'post': 'create'}), name='sale-create') ] diff --git a/tienda_ilusion/tienda_ilusion/settings.py b/tienda_ilusion/tienda_ilusion/settings.py index e50d393..807d758 100644 --- a/tienda_ilusion/tienda_ilusion/settings.py +++ b/tienda_ilusion/tienda_ilusion/settings.py @@ -38,6 +38,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'rest_framework', # 'don_confiao' ] -- 2.45.2 From 5adf9a9ce7bb7880a83c4c927649b5141956d75f Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sun, 8 Sep 2024 21:42:35 -0500 Subject: [PATCH 2/3] feat(api): implement endpoints to products, customer and sales. --- tienda_ilusion/don_confiao/api_views.py | 21 +++++++++++++--- tienda_ilusion/don_confiao/serializers.py | 26 ++++++++++++++++++-- tienda_ilusion/don_confiao/tests/test_api.py | 19 +++++++++++++- tienda_ilusion/don_confiao/urls.py | 13 ++++++++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/tienda_ilusion/don_confiao/api_views.py b/tienda_ilusion/don_confiao/api_views.py index d5fc155..de798eb 100644 --- a/tienda_ilusion/don_confiao/api_views.py +++ b/tienda_ilusion/don_confiao/api_views.py @@ -2,12 +2,12 @@ from rest_framework import viewsets from rest_framework.response import Response from .models import Sale, SaleLine, Customer, Product -from .serializers import SaleSerializer +from .serializers import SaleSerializer, SaleWithLinesSerializer, ProductSerializer, CustomerSerializer -class SaleViewSet(viewsets.ModelViewSet): +class SaleWithLinesViewSet(viewsets.ModelViewSet): queryset = Sale.objects.all() - serializer_class = SaleSerializer + serializer_class = SaleWithLinesSerializer def create(self, request): data = request.data @@ -28,3 +28,18 @@ class SaleViewSet(viewsets.ModelViewSet): ) return Response({'message': 'Venta creada con exito'}, status=201) + + +class SaleView(viewsets.ModelViewSet): + queryset = Sale.objects.all() + serializer_class = SaleSerializer + + +class ProductView(viewsets.ModelViewSet): + queryset = Product.objects.all() + serializer_class = ProductSerializer + + +class CustomerView(viewsets.ModelViewSet): + queryset = Customer.objects.all() + serializer_class = CustomerSerializer diff --git a/tienda_ilusion/don_confiao/serializers.py b/tienda_ilusion/don_confiao/serializers.py index 464c6f8..7e67f0b 100644 --- a/tienda_ilusion/don_confiao/serializers.py +++ b/tienda_ilusion/don_confiao/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from .models import Sale, SaleLine +from .models import Sale, SaleLine, Product, Customer class SaleLineSerializer(serializers.ModelSerializer): @@ -9,9 +9,31 @@ class SaleLineSerializer(serializers.ModelSerializer): fields = ['id', 'sale', 'product', 'unit_price', 'quantity'] -class SaleSerializer(serializers.ModelSerializer): +class SaleWithLinesSerializer(serializers.ModelSerializer): lines = SaleLineSerializer(many=True) class Meta: model = Sale fields = ['id', 'customer', 'date', 'lines'] + + +class SaleSerializer(serializers.ModelSerializer): + class Meta: + model = Sale + fields = ['id', 'customer', 'date'] + + def to_representation(self, instance): + representation = super().to_representation(instance) + representation['lines'] = [line for line in instance.saleline_set.all().values()] + return representation + + +class ProductSerializer(serializers.ModelSerializer): + class Meta: + model = Product + fields = ['name', 'price', 'measuring_unit', 'categories'] + +class CustomerSerializer(serializers.ModelSerializer): + class Meta: + model = Customer + fields = ['name', 'address'] diff --git a/tienda_ilusion/don_confiao/tests/test_api.py b/tienda_ilusion/don_confiao/tests/test_api.py index 5a9cb90..7a2d3af 100644 --- a/tienda_ilusion/don_confiao/tests/test_api.py +++ b/tienda_ilusion/don_confiao/tests/test_api.py @@ -29,4 +29,21 @@ class TestAPI(APITestCase): response = self.client.post(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(Sale.objects.count(), 1) - self.assertEqual(Sale.objects.all()[0].customer.name, self.customer.name) + self.assertEqual( + Sale.objects.all()[0].customer.name, + self.customer.name + ) + + def test_get_products(self): + url = '/don_confiao/api/products/' + response = self.client.get(url) + json_response = json.loads(response.content.decode('utf-8')) + self.assertEqual(response.status_code, 200) + self.assertEqual(self.product.name, json_response[0]['name']) + + def test_get_customers(self): + url = '/don_confiao/api/customers/' + response = self.client.get(url) + json_response = json.loads(response.content.decode('utf-8')) + self.assertEqual(response.status_code, 200) + self.assertEqual(self.customer.name, json_response[0]['name']) diff --git a/tienda_ilusion/don_confiao/urls.py b/tienda_ilusion/don_confiao/urls.py index 145c70a..168b8d3 100644 --- a/tienda_ilusion/don_confiao/urls.py +++ b/tienda_ilusion/don_confiao/urls.py @@ -1,9 +1,17 @@ -from django.urls import path +from django.urls import path, include +from rest_framework.routers import DefaultRouter from . import views from . import api_views app_name = 'don_confiao' + +router = DefaultRouter() +router.register(r'sales', api_views.SaleView, basename='sale') +router.register(r'customers', api_views.CustomerView, basename='customer') +router.register(r'products', api_views.ProductView, basename='product') + + urlpatterns = [ path("", views.index, name="wellcome"), path("comprar", views.buy, name="buy"), @@ -14,5 +22,6 @@ urlpatterns = [ path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"), path("cuadres", views.reconciliate_jar, name="reconciliations"), path("resumen_compra/", views.purchase_summary, name="purchase_summary"), - path('api/sales/', api_views.SaleViewSet.as_view({'post': 'create'}), name='sale-create') + path('api/sales_with_lines/', api_views.SaleWithLinesViewSet.as_view({'post': 'create'}), name='sale-create'), + path('api/', include(router.urls)), ] -- 2.45.2 From 19a618a671449883f541a11c63fc6b369c4a4945 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sun, 8 Sep 2024 22:33:41 -0500 Subject: [PATCH 3/3] fix(api): remove SaleWithLinesViewSet. --- tienda_ilusion/don_confiao/api_views.py | 13 ++++--------- tienda_ilusion/don_confiao/serializers.py | 15 +-------------- tienda_ilusion/don_confiao/tests/test_api.py | 2 +- tienda_ilusion/don_confiao/urls.py | 1 - 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/tienda_ilusion/don_confiao/api_views.py b/tienda_ilusion/don_confiao/api_views.py index de798eb..95be792 100644 --- a/tienda_ilusion/don_confiao/api_views.py +++ b/tienda_ilusion/don_confiao/api_views.py @@ -2,18 +2,18 @@ from rest_framework import viewsets from rest_framework.response import Response from .models import Sale, SaleLine, Customer, Product -from .serializers import SaleSerializer, SaleWithLinesSerializer, ProductSerializer, CustomerSerializer +from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer -class SaleWithLinesViewSet(viewsets.ModelViewSet): +class SaleView(viewsets.ModelViewSet): queryset = Sale.objects.all() - serializer_class = SaleWithLinesSerializer + serializer_class = SaleSerializer def create(self, request): data = request.data customer = Customer.objects.get(pk=data['customer']) date = data['date'] - lines = data['lines'] + lines = data['saleline_set'] sale = Sale.objects.create(customer=customer, date=date) for line in lines: @@ -30,11 +30,6 @@ class SaleWithLinesViewSet(viewsets.ModelViewSet): return Response({'message': 'Venta creada con exito'}, status=201) -class SaleView(viewsets.ModelViewSet): - queryset = Sale.objects.all() - serializer_class = SaleSerializer - - class ProductView(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer diff --git a/tienda_ilusion/don_confiao/serializers.py b/tienda_ilusion/don_confiao/serializers.py index 7e67f0b..df664c7 100644 --- a/tienda_ilusion/don_confiao/serializers.py +++ b/tienda_ilusion/don_confiao/serializers.py @@ -9,23 +9,10 @@ class SaleLineSerializer(serializers.ModelSerializer): fields = ['id', 'sale', 'product', 'unit_price', 'quantity'] -class SaleWithLinesSerializer(serializers.ModelSerializer): - lines = SaleLineSerializer(many=True) - - class Meta: - model = Sale - fields = ['id', 'customer', 'date', 'lines'] - - class SaleSerializer(serializers.ModelSerializer): class Meta: model = Sale - fields = ['id', 'customer', 'date'] - - def to_representation(self, instance): - representation = super().to_representation(instance) - representation['lines'] = [line for line in instance.saleline_set.all().values()] - return representation + fields = ['id', 'customer', 'date', 'saleline_set'] class ProductSerializer(serializers.ModelSerializer): diff --git a/tienda_ilusion/don_confiao/tests/test_api.py b/tienda_ilusion/don_confiao/tests/test_api.py index 7a2d3af..6abc196 100644 --- a/tienda_ilusion/don_confiao/tests/test_api.py +++ b/tienda_ilusion/don_confiao/tests/test_api.py @@ -21,7 +21,7 @@ class TestAPI(APITestCase): data = { 'customer': self.customer.id, 'date': '2024-09-02', - 'lines': [ + 'saleline_set': [ {'product': self.product.id, 'quantity': 2, 'unit_price': 3000}, {'product': self.product.id, 'quantity': 3, 'unit_price': 5000} ], diff --git a/tienda_ilusion/don_confiao/urls.py b/tienda_ilusion/don_confiao/urls.py index 168b8d3..0e6aa88 100644 --- a/tienda_ilusion/don_confiao/urls.py +++ b/tienda_ilusion/don_confiao/urls.py @@ -22,6 +22,5 @@ urlpatterns = [ path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"), path("cuadres", views.reconciliate_jar, name="reconciliations"), path("resumen_compra/", views.purchase_summary, name="purchase_summary"), - path('api/sales_with_lines/', api_views.SaleWithLinesViewSet.as_view({'post': 'create'}), name='sale-create'), path('api/', include(router.urls)), ] -- 2.45.2