Feat: Export Ventas Para Tryton
This commit is contained in:
		
							
								
								
									
										1
									
								
								tienda_ilusion/don_confiao/export_csv.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tienda_ilusion/don_confiao/export_csv.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| #!/usr/bin/env python3 | ||||
| @@ -13,6 +13,7 @@ class Customer(models.Model): | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|  | ||||
| class MeasuringUnits(models.TextChoices): | ||||
|     UNIT = 'UNIT', _('Unit') | ||||
|  | ||||
| @@ -62,11 +63,16 @@ class Sale(models.Model): | ||||
|     def __str__(self): | ||||
|         return f"{self.date} {self.customer}" | ||||
|  | ||||
|  | ||||
|     def get_total(self): | ||||
|         lines = self.saleline_set.all() | ||||
|         return sum([l.quantity * l.unit_price for l in lines]) | ||||
|  | ||||
|     @classmethod | ||||
|     def sale_header_csv(cls): | ||||
|         sale_header_csv = [field.name for field in cls._meta.fields] | ||||
|  | ||||
|         return sale_header_csv | ||||
|  | ||||
|  | ||||
| class SaleLine(models.Model): | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
|     "model": "don_confiao.productcategory", | ||||
|     "pk": 1, | ||||
|     "fields": { | ||||
|       "name": "Unidad", | ||||
|       "name": "Unidad" | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
| @@ -20,7 +20,7 @@ | ||||
|     "fields": { | ||||
|       "name": "Papaya", | ||||
|       "price": 2500, | ||||
|       "measuring_unit": "Unidad", | ||||
|       "measuring_unit": "Unidad" | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
| @@ -32,5 +32,16 @@ | ||||
|       "phone": 312201103, | ||||
|       "description": "Primera Venta" | ||||
|     } | ||||
|   }, | ||||
|     { | ||||
|         "model": "don_confiao.saleline", | ||||
|         "pk": 1, | ||||
|         "fields": { | ||||
|             "sale": 1, | ||||
|             "product": 1, | ||||
|             "quantity": 10, | ||||
|             "unit_price": 5000, | ||||
|             "description": "Primer Sale Line" | ||||
|         } | ||||
|     } | ||||
| ] | ||||
|   | ||||
| @@ -1,16 +1,50 @@ | ||||
| #!/usr/bin/env python3 | ||||
| from django.test import TestCase | ||||
| from ..models import Sale | ||||
| from django.test import Client, TestCase | ||||
| from io import StringIO | ||||
| import csv | ||||
|  | ||||
|  | ||||
| class TestExportSales(TestCase): | ||||
|     fixtures = ['sales_fixture'] | ||||
|  | ||||
|     def setUp(self): | ||||
|         pass | ||||
|         self.client = Client() | ||||
|  | ||||
|     def test_export_sales(self): | ||||
|         sales = self._export_sales_csv() | ||||
|         self.assertEqual(len(sales), 1) | ||||
|         sales_response = self._export_sales_csv() | ||||
|         filename = sales_response.headers[ | ||||
|             'Content-Disposition'].split('; ')[1].strip('filename=').strip("'") | ||||
|         content = sales_response.content | ||||
|         content_str = content.decode('utf-8') | ||||
|         csv_file = StringIO(content_str) | ||||
|         header = next(csv.reader(csv_file)) | ||||
|  | ||||
|         self.assertGreater(len(content), 0) | ||||
|         self.assertEqual(filename, 'sales.csv') | ||||
|         self.assertEqual(sales_response.headers['Content-Type'], 'text/csv') | ||||
|         self.assertEqual(header, self._tryton_sale_header()) | ||||
|  | ||||
|     def _export_sales_csv(self): | ||||
|         raise Exception(Sale.objects.all()) | ||||
|         return self.client.get("/don_confiao/exportar_ventas_para_tryton") | ||||
|  | ||||
|     def _tryton_sale_header(self): | ||||
|         return [ | ||||
|             "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" | ||||
|                 ] | ||||
|   | ||||
| @@ -10,6 +10,9 @@ urlpatterns = [ | ||||
|     path("productos", views.products, name="products"), | ||||
|     path("lista_productos", views.ProductListView.as_view(), name='product_list'), | ||||
|     path("importar_productos", views.import_products, name="import_products"), | ||||
|     path("exportar_ventas_para_tryton", | ||||
|          views.exportar_ventas_para_tryton, | ||||
|          name="exportar_ventas_para_tryton"), | ||||
|     path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"), | ||||
|     path("cuadres", views.reconciliate_jar, name="reconciliations"), | ||||
|     path("resumen_compra/<int:id>", views.purchase_summary, name="purchase_summary"), | ||||
|   | ||||
| @@ -3,8 +3,14 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse | ||||
| from django.views.generic import ListView | ||||
| from django.db import transaction | ||||
|  | ||||
| from .models import Sale, Product, ProductCategory, Payment, PaymentMethods | ||||
| from .forms import ImportProductsForm, PurchaseForm, SaleLineFormSet, ReconciliationJarForm, PurchaseSummaryForm | ||||
| from .models import ( | ||||
|     Sale, SaleLine, Product, ProductCategory, Payment, PaymentMethods) | ||||
| from .forms import ( | ||||
|     ImportProductsForm, | ||||
|     PurchaseForm, | ||||
|     SaleLineFormSet, | ||||
|     ReconciliationJarForm, | ||||
|     PurchaseSummaryForm) | ||||
|  | ||||
| import csv | ||||
| import io | ||||
| @@ -18,9 +24,11 @@ class DecimalEncoder(json.JSONEncoder): | ||||
|             return float(obj) | ||||
|         return json.JSONEncoder.default(self, obj) | ||||
|  | ||||
|  | ||||
| def index(request): | ||||
|     return render(request, 'don_confiao/index.html') | ||||
|  | ||||
|  | ||||
| def buy(request): | ||||
|     if request.method == "POST": | ||||
|         sale_form = PurchaseForm(request.POST) | ||||
| @@ -115,10 +123,11 @@ def purchase_summary(request, id): | ||||
|         request, | ||||
|         "don_confiao/purchase_summary.html", | ||||
|         { | ||||
|             "purchase" : purchase | ||||
|             "purchase": purchase | ||||
|         } | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def _categories_from_csv_string(categories_string, separator="&"): | ||||
|     categories = categories_string.split(separator) | ||||
|     clean_categories = [c.strip() for c in categories] | ||||
| @@ -146,6 +155,70 @@ def handle_import_products_file(csv_file): | ||||
|             product.categories.add(category) | ||||
|  | ||||
|  | ||||
| def exportar_ventas_para_tryton(request): | ||||
|     tryton_sales_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" | ||||
|     ] | ||||
|  | ||||
|     if request.method == "GET": | ||||
|         response = HttpResponse(content_type='text/csv') | ||||
|         response['Content-Disposition'] = "attachment; filename=sales.csv" | ||||
|         writer = csv.writer(response) | ||||
|         writer.writerow(tryton_sales_header) | ||||
|  | ||||
|         sales = Sale.objects.all() | ||||
|  | ||||
|         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, | ||||
|                 "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 | ||||
|  | ||||
|  | ||||
| class ProductListView(ListView): | ||||
|     model = Product | ||||
|     template_model = 'don_confiao/product_list.html' | ||||
|   | ||||
| @@ -123,3 +123,5 @@ STATIC_URL = 'static/' | ||||
| # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field | ||||
|  | ||||
| DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' | ||||
|  | ||||
| FIXTURE_DIRS = ['don_confiao/tests/Fixtures'] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user