Exportando ventas para tryton desde api #4
@@ -6,9 +6,11 @@ from rest_framework.pagination import PageNumberPagination
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from .models import Sale, SaleLine, Customer, Product, ReconciliationJar, PaymentMethods, AdminCode
 | 
					from .models import Sale, SaleLine, Customer, Product, ReconciliationJar, PaymentMethods, AdminCode
 | 
				
			||||||
from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, ReconciliationJarSerializer, PaymentMethodSerializer, SaleForRenconciliationSerializer, SaleSummarySerializer
 | 
					from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, ReconciliationJarSerializer, PaymentMethodSerializer, SaleForRenconciliationSerializer, SaleSummarySerializer
 | 
				
			||||||
 | 
					from .views import sales_to_tryton_csv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from decimal import Decimal
 | 
					from decimal import Decimal
 | 
				
			||||||
import json
 | 
					import io
 | 
				
			||||||
 | 
					import csv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Pagination(PageNumberPagination):
 | 
					class Pagination(PageNumberPagination):
 | 
				
			||||||
@@ -128,12 +130,14 @@ class SalesForReconciliationView(APIView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return Response(grouped_sales)
 | 
					        return Response(grouped_sales)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SaleSummary(APIView):
 | 
					class SaleSummary(APIView):
 | 
				
			||||||
    def get(self, request, id):
 | 
					    def get(self, request, id):
 | 
				
			||||||
        sale = Sale.objects.get(pk=id)
 | 
					        sale = Sale.objects.get(pk=id)
 | 
				
			||||||
        serializer = SaleSummarySerializer(sale)
 | 
					        serializer = SaleSummarySerializer(sale)
 | 
				
			||||||
        return Response(serializer.data)
 | 
					        return Response(serializer.data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AdminCodeValidateView(APIView):
 | 
					class AdminCodeValidateView(APIView):
 | 
				
			||||||
    def get(self, request, code):
 | 
					    def get(self, request, code):
 | 
				
			||||||
        codes = AdminCode.objects.filter(value=code)
 | 
					        codes = AdminCode.objects.filter(value=code)
 | 
				
			||||||
@@ -144,3 +148,19 @@ class ReconciliateJarModelView(viewsets.ModelViewSet):
 | 
				
			|||||||
    queryset = ReconciliationJar.objects.all().order_by('-date_time')
 | 
					    queryset = ReconciliationJar.objects.all().order_by('-date_time')
 | 
				
			||||||
    pagination_class = Pagination
 | 
					    pagination_class = Pagination
 | 
				
			||||||
    serializer_class = ReconciliationJarSerializer
 | 
					    serializer_class = ReconciliationJarSerializer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SalesForTrytonView(APIView):
 | 
				
			||||||
 | 
					    def get(self, request):
 | 
				
			||||||
 | 
					        sales = Sale.objects.all()
 | 
				
			||||||
 | 
					        csv = self._generate_sales_CSV(sales)
 | 
				
			||||||
 | 
					        return Response({'csv': csv})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _generate_sales_CSV(self, sales):
 | 
				
			||||||
 | 
					        output = io.StringIO()
 | 
				
			||||||
 | 
					        writer = csv.writer(output)
 | 
				
			||||||
 | 
					        csv_data = sales_to_tryton_csv(sales)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for row in csv_data:
 | 
				
			||||||
 | 
					            writer.writerow(row)
 | 
				
			||||||
 | 
					        return output.getvalue()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,7 @@
 | 
				
			|||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					import csv
 | 
				
			||||||
 | 
					import io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
from rest_framework import status
 | 
					from rest_framework import status
 | 
				
			||||||
from rest_framework.test import APITestCase
 | 
					from rest_framework.test import APITestCase
 | 
				
			||||||
@@ -45,6 +48,58 @@ class TestAPI(APITestCase):
 | 
				
			|||||||
        self.assertEqual(response.status_code, 200)
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
        self.assertEqual(self.customer.name, json_response[0]['name'])
 | 
					        self.assertEqual(self.customer.name, json_response[0]['name'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_get_sales_for_tryton(self):
 | 
				
			||||||
 | 
					        url = '/don_confiao/api/sales/for_tryton'
 | 
				
			||||||
 | 
					        self._create_sale()
 | 
				
			||||||
 | 
					        response = self.client.get(url)
 | 
				
			||||||
 | 
					        json_response = json.loads(response.content.decode('utf-8'))
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, status.HTTP_200_OK)
 | 
				
			||||||
 | 
					        self.assertIn('csv', json_response)
 | 
				
			||||||
 | 
					        self.assertGreater(len(json_response['csv']), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_csv_structure_in_sales_for_tryton(self):
 | 
				
			||||||
 | 
					        url = '/don_confiao/api/sales/for_tryton'
 | 
				
			||||||
 | 
					        self._create_sale()
 | 
				
			||||||
 | 
					        response = self.client.get(url)
 | 
				
			||||||
 | 
					        json_response = json.loads(response.content.decode('utf-8'))
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, status.HTTP_200_OK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        csv_reader = csv.reader(io.StringIO(json_response['csv']))
 | 
				
			||||||
 | 
					        expected_header = [
 | 
				
			||||||
 | 
					            "Tercero",
 | 
				
			||||||
 | 
					            "Dirección de facturación",
 | 
				
			||||||
 | 
					            "Dirección de envío",
 | 
				
			||||||
 | 
					            "Descripción",
 | 
				
			||||||
 | 
					            "Referencia",
 | 
				
			||||||
 | 
					            "Fecha venta",
 | 
				
			||||||
 | 
					            "Plazo de pago",
 | 
				
			||||||
 | 
					            "Almacén",
 | 
				
			||||||
 | 
					            "Moneda",
 | 
				
			||||||
 | 
					            "Líneas/Producto",
 | 
				
			||||||
 | 
					            "Líneas/Cantidad",
 | 
				
			||||||
 | 
					            "Líneas/Precio unitario",
 | 
				
			||||||
 | 
					            "Líneas/Unidad",
 | 
				
			||||||
 | 
					            "Empresa",
 | 
				
			||||||
 | 
					            "Tienda",
 | 
				
			||||||
 | 
					            "Terminal de venta",
 | 
				
			||||||
 | 
					            "Autorecogida",
 | 
				
			||||||
 | 
					            "Comentario"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        self.assertEqual(next(csv_reader), expected_header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expected_rows = [
 | 
				
			||||||
 | 
					            [self.customer.name, self.customer.name, self.customer.name, "",
 | 
				
			||||||
 | 
					             "", "2024-09-02 00:00:00+00:00", "Contado", "Almacén",
 | 
				
			||||||
 | 
					             "Peso colombiano", self.product.name, "2", "3000.00", "Unidad",
 | 
				
			||||||
 | 
					             "TIENDA LA ILUSIÓN", "Tienda La Ilusion", "La Ilusion", "True", ""
 | 
				
			||||||
 | 
					             ],
 | 
				
			||||||
 | 
					            ["", "", "", "", "", "", "", "", "", self.product.name, "3",
 | 
				
			||||||
 | 
					             "5000.00", "Unidad", "", "", "", "", ""
 | 
				
			||||||
 | 
					             ],
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        rows = list(csv_reader)
 | 
				
			||||||
 | 
					        self.assertEqual(rows, expected_rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _create_sale(self):
 | 
					    def _create_sale(self):
 | 
				
			||||||
        url = '/don_confiao/api/sales/'
 | 
					        url = '/don_confiao/api/sales/'
 | 
				
			||||||
        data = {
 | 
					        data = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					import csv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.test import TestCase, Client
 | 
				
			||||||
 | 
					from django.urls import reverse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ..models import Sale, SaleLine, Product, Customer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestExportarVentasParaTryton(TestCase):
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        self.product = Product.objects.create(
 | 
				
			||||||
 | 
					            name='Panela',
 | 
				
			||||||
 | 
					            price=5000,
 | 
				
			||||||
 | 
					            measuring_unit='UNIT'
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.customer = Customer.objects.create(
 | 
				
			||||||
 | 
					            name='Camilo'
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.sale = Sale.objects.create(
 | 
				
			||||||
 | 
					            customer=self.customer,
 | 
				
			||||||
 | 
					            date='2024-09-02',
 | 
				
			||||||
 | 
					            payment_method='CASH',
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.sale_line1 = SaleLine.objects.create(
 | 
				
			||||||
 | 
					            product=self.product,
 | 
				
			||||||
 | 
					            quantity=2,
 | 
				
			||||||
 | 
					            unit_price=3000,
 | 
				
			||||||
 | 
					            sale=self.sale
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.sale_line2 = SaleLine.objects.create(
 | 
				
			||||||
 | 
					            product=self.product,
 | 
				
			||||||
 | 
					            quantity=3,
 | 
				
			||||||
 | 
					            unit_price=5000,
 | 
				
			||||||
 | 
					            sale=self.sale
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_exportar_ventas_para_tryton(self):
 | 
				
			||||||
 | 
					        client = Client()
 | 
				
			||||||
 | 
					        url = '/don_confiao/exportar_ventas_para_tryton'
 | 
				
			||||||
 | 
					        response = client.get(url)
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        self.assertEqual(response['Content-Type'], 'text/csv')
 | 
				
			||||||
 | 
					        csv_content = response.content.decode('utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expected_header = [
 | 
				
			||||||
 | 
					            "Tercero",
 | 
				
			||||||
 | 
					            "Dirección de facturación",
 | 
				
			||||||
 | 
					            "Dirección de envío",
 | 
				
			||||||
 | 
					            "Descripción",
 | 
				
			||||||
 | 
					            "Referencia",
 | 
				
			||||||
 | 
					            "Fecha venta",
 | 
				
			||||||
 | 
					            "Plazo de pago",
 | 
				
			||||||
 | 
					            "Almacén",
 | 
				
			||||||
 | 
					            "Moneda",
 | 
				
			||||||
 | 
					            "Líneas/Producto",
 | 
				
			||||||
 | 
					            "Líneas/Cantidad",
 | 
				
			||||||
 | 
					            "Líneas/Precio unitario",
 | 
				
			||||||
 | 
					            "Líneas/Unidad",
 | 
				
			||||||
 | 
					            "Empresa",
 | 
				
			||||||
 | 
					            "Tienda",
 | 
				
			||||||
 | 
					            "Terminal de venta",
 | 
				
			||||||
 | 
					            "Autorecogida",
 | 
				
			||||||
 | 
					            "Comentario"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        csv_reader = csv.reader(csv_content.splitlines())
 | 
				
			||||||
 | 
					        self.assertEqual(next(csv_reader), expected_header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expected_rows = [
 | 
				
			||||||
 | 
					            ["Camilo", "Camilo", "Camilo", "", "", "2024-09-02 00:00:00+00:00", "Contado", "Almacén", "Peso colombiano", "Panela", "2", "3000.00", "Unidad", "TIENDA LA ILUSIÓN", "Tienda La Ilusion", "La Ilusion", "True", ""],
 | 
				
			||||||
 | 
					            ["", "", "", "", "", "", "", "", "", "Panela", "3", "5000.00", "Unidad", "", "", "", "", ""],
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        csv_rows = list(csv_reader)
 | 
				
			||||||
 | 
					        self.assertEqual(csv_rows[0], expected_rows[0])
 | 
				
			||||||
 | 
					        self.assertEqual(csv_rows[1], expected_rows[1])
 | 
				
			||||||
@@ -30,5 +30,6 @@ urlpatterns = [
 | 
				
			|||||||
    path('purchases/for_reconciliation', api_views.SalesForReconciliationView.as_view(), name='sales_for_reconciliation'),
 | 
					    path('purchases/for_reconciliation', api_views.SalesForReconciliationView.as_view(), name='sales_for_reconciliation'),
 | 
				
			||||||
    path('reconciliate_jar', api_views.ReconciliateJarView.as_view()),
 | 
					    path('reconciliate_jar', api_views.ReconciliateJarView.as_view()),
 | 
				
			||||||
    path('api/admin_code/validate/<code>', api_views.AdminCodeValidateView.as_view()),
 | 
					    path('api/admin_code/validate/<code>', api_views.AdminCodeValidateView.as_view()),
 | 
				
			||||||
 | 
					    path('api/sales/for_tryton', api_views.SalesForTrytonView.as_view()),
 | 
				
			||||||
    path('api/', include(router.urls)),
 | 
					    path('api/', include(router.urls)),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -163,8 +163,7 @@ def handle_import_customers_file(csv_file):
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def sales_to_tryton_csv(sales):
 | 
				
			||||||
def exportar_ventas_para_tryton(request):
 | 
					 | 
				
			||||||
    tryton_sales_header = [
 | 
					    tryton_sales_header = [
 | 
				
			||||||
        "Tercero",
 | 
					        "Tercero",
 | 
				
			||||||
        "Dirección de facturación",
 | 
					        "Dirección de facturación",
 | 
				
			||||||
@@ -186,44 +185,50 @@ def exportar_ventas_para_tryton(request):
 | 
				
			|||||||
        "Comentario"
 | 
					        "Comentario"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    csv_data = [tryton_sales_header]
 | 
				
			||||||
 | 
					    for sale in sales:
 | 
				
			||||||
 | 
					        sale_lines = SaleLine.objects.filter(sale=sale.id)
 | 
				
			||||||
 | 
					        if not sale_lines:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        lines = []
 | 
				
			||||||
 | 
					        first_sale_line = sale_lines[0]
 | 
				
			||||||
 | 
					        customer_info = [sale.customer.name] * 3 + [sale.description] * 2
 | 
				
			||||||
 | 
					        first_line = customer_info + [
 | 
				
			||||||
 | 
					            sale.date,
 | 
				
			||||||
 | 
					            "Contado",
 | 
				
			||||||
 | 
					            "Almacén",
 | 
				
			||||||
 | 
					            "Peso colombiano",
 | 
				
			||||||
 | 
					            first_sale_line.product.name,
 | 
				
			||||||
 | 
					            first_sale_line.quantity,
 | 
				
			||||||
 | 
					            first_sale_line.unit_price,
 | 
				
			||||||
 | 
					            "Unidad",
 | 
				
			||||||
 | 
					            "TIENDA LA ILUSIÓN",
 | 
				
			||||||
 | 
					            "Tienda La Ilusion",
 | 
				
			||||||
 | 
					            "La Ilusion",
 | 
				
			||||||
 | 
					            True,
 | 
				
			||||||
 | 
					            sale.description]
 | 
				
			||||||
 | 
					        lines.append(first_line)
 | 
				
			||||||
 | 
					        for line in sale_lines[1:]:
 | 
				
			||||||
 | 
					            lines.append([""]*9+[
 | 
				
			||||||
 | 
					                line.product.name,
 | 
				
			||||||
 | 
					                line.quantity,
 | 
				
			||||||
 | 
					                line.unit_price,
 | 
				
			||||||
 | 
					                "Unidad"]+[""]*5)
 | 
				
			||||||
 | 
					        for row in lines:
 | 
				
			||||||
 | 
					            csv_data.append(row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return csv_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def exportar_ventas_para_tryton(request):
 | 
				
			||||||
    if request.method == "GET":
 | 
					    if request.method == "GET":
 | 
				
			||||||
        response = HttpResponse(content_type='text/csv')
 | 
					        response = HttpResponse(content_type='text/csv')
 | 
				
			||||||
        response['Content-Disposition'] = "attachment; filename=sales.csv"
 | 
					        response['Content-Disposition'] = "attachment; filename=sales.csv"
 | 
				
			||||||
        writer = csv.writer(response)
 | 
					 | 
				
			||||||
        writer.writerow(tryton_sales_header)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sales = Sale.objects.all()
 | 
					        sales = Sale.objects.all()
 | 
				
			||||||
 | 
					        csv_data = sales_to_tryton_csv(sales)
 | 
				
			||||||
        for sale in sales:
 | 
					        writer = csv.writer(response)
 | 
				
			||||||
            sale_lines = SaleLine.objects.filter(sale=sale.id)
 | 
					        for row in csv_data:
 | 
				
			||||||
            if not sale_lines:
 | 
					            writer.writerow(row)
 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            lines = []
 | 
					 | 
				
			||||||
            first_sale_line = sale_lines[0]
 | 
					 | 
				
			||||||
            customer_info = [sale.customer.name] * 3 + [sale.description] * 2
 | 
					 | 
				
			||||||
            first_line = customer_info + [
 | 
					 | 
				
			||||||
                sale.date,
 | 
					 | 
				
			||||||
                "Contado",
 | 
					 | 
				
			||||||
                "Almacén",
 | 
					 | 
				
			||||||
                "Peso colombiano",
 | 
					 | 
				
			||||||
                first_sale_line.product.name,
 | 
					 | 
				
			||||||
                first_sale_line.quantity,
 | 
					 | 
				
			||||||
                "Unidad",
 | 
					 | 
				
			||||||
                first_sale_line.unit_price,
 | 
					 | 
				
			||||||
                "TIENDA LA ILUSIÓN",
 | 
					 | 
				
			||||||
                "Tienda La Ilusion",
 | 
					 | 
				
			||||||
                "La Ilusion",
 | 
					 | 
				
			||||||
                True,
 | 
					 | 
				
			||||||
                sale.description]
 | 
					 | 
				
			||||||
            lines.append(first_line)
 | 
					 | 
				
			||||||
            for line in sale_lines[1:]:
 | 
					 | 
				
			||||||
                lines.append([""]*9+[
 | 
					 | 
				
			||||||
                    line.product.name,
 | 
					 | 
				
			||||||
                    line.quantity,
 | 
					 | 
				
			||||||
                    line.unit_price,
 | 
					 | 
				
			||||||
                    "Unidad"]+[""]*5)
 | 
					 | 
				
			||||||
            for row in lines:
 | 
					 | 
				
			||||||
                writer.writerow(row)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return response
 | 
					        return response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user