Merge branch 'main' into implement_api
This commit is contained in:
commit
86b231a828
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):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class MeasuringUnits(models.TextChoices):
|
class MeasuringUnits(models.TextChoices):
|
||||||
UNIT = 'UNIT', _('Unit')
|
UNIT = 'UNIT', _('Unit')
|
||||||
|
|
||||||
@ -62,11 +63,16 @@ class Sale(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.date} {self.customer}"
|
return f"{self.date} {self.customer}"
|
||||||
|
|
||||||
|
|
||||||
def get_total(self):
|
def get_total(self):
|
||||||
lines = self.saleline_set.all()
|
lines = self.saleline_set.all()
|
||||||
return sum([l.quantity * l.unit_price for l in lines])
|
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):
|
class SaleLine(models.Model):
|
||||||
|
|
||||||
|
47
tienda_ilusion/don_confiao/tests/Fixtures/sales_fixture.json
Normal file
47
tienda_ilusion/don_confiao/tests/Fixtures/sales_fixture.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"model": "don_confiao.customer",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"name": "Alejandro Fernandez",
|
||||||
|
"address": "Avenida Siempre Viva"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "don_confiao.productcategory",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"name": "Unidad"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "don_confiao.product",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"name": "Papaya",
|
||||||
|
"price": 2500,
|
||||||
|
"measuring_unit": "Unidad"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "don_confiao.sale",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"customer": 1,
|
||||||
|
"date": "2024-08-31",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
50
tienda_ilusion/don_confiao/tests/test_export_sales.py
Normal file
50
tienda_ilusion/don_confiao/tests/test_export_sales.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from django.test import Client, TestCase
|
||||||
|
from io import StringIO
|
||||||
|
import csv
|
||||||
|
|
||||||
|
|
||||||
|
class TestExportSales(TestCase):
|
||||||
|
fixtures = ['sales_fixture']
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.client = Client()
|
||||||
|
|
||||||
|
def test_export_sales(self):
|
||||||
|
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):
|
||||||
|
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"
|
||||||
|
]
|
@ -19,6 +19,9 @@ urlpatterns = [
|
|||||||
path("productos", views.products, name="products"),
|
path("productos", views.products, name="products"),
|
||||||
path("lista_productos", views.ProductListView.as_view(), name='product_list'),
|
path("lista_productos", views.ProductListView.as_view(), name='product_list'),
|
||||||
path("importar_productos", views.import_products, name="import_products"),
|
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("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"),
|
||||||
path("cuadres", views.reconciliate_jar, name="reconciliations"),
|
path("cuadres", views.reconciliate_jar, name="reconciliations"),
|
||||||
path("resumen_compra/<int:id>", views.purchase_summary, name="purchase_summary"),
|
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.views.generic import ListView
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
from .models import Sale, Product, ProductCategory, Payment, PaymentMethods
|
from .models import (
|
||||||
from .forms import ImportProductsForm, PurchaseForm, SaleLineFormSet, ReconciliationJarForm, PurchaseSummaryForm
|
Sale, SaleLine, Product, ProductCategory, Payment, PaymentMethods)
|
||||||
|
from .forms import (
|
||||||
|
ImportProductsForm,
|
||||||
|
PurchaseForm,
|
||||||
|
SaleLineFormSet,
|
||||||
|
ReconciliationJarForm,
|
||||||
|
PurchaseSummaryForm)
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import io
|
import io
|
||||||
@ -18,9 +24,11 @@ class DecimalEncoder(json.JSONEncoder):
|
|||||||
return float(obj)
|
return float(obj)
|
||||||
return json.JSONEncoder.default(self, obj)
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return render(request, 'don_confiao/index.html')
|
return render(request, 'don_confiao/index.html')
|
||||||
|
|
||||||
|
|
||||||
def buy(request):
|
def buy(request):
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
sale_form = PurchaseForm(request.POST)
|
sale_form = PurchaseForm(request.POST)
|
||||||
@ -115,10 +123,11 @@ def purchase_summary(request, id):
|
|||||||
request,
|
request,
|
||||||
"don_confiao/purchase_summary.html",
|
"don_confiao/purchase_summary.html",
|
||||||
{
|
{
|
||||||
"purchase" : purchase
|
"purchase": purchase
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _categories_from_csv_string(categories_string, separator="&"):
|
def _categories_from_csv_string(categories_string, separator="&"):
|
||||||
categories = categories_string.split(separator)
|
categories = categories_string.split(separator)
|
||||||
clean_categories = [c.strip() for c in categories]
|
clean_categories = [c.strip() for c in categories]
|
||||||
@ -146,6 +155,70 @@ def handle_import_products_file(csv_file):
|
|||||||
product.categories.add(category)
|
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):
|
class ProductListView(ListView):
|
||||||
model = Product
|
model = Product
|
||||||
template_model = 'don_confiao/product_list.html'
|
template_model = 'don_confiao/product_list.html'
|
||||||
|
@ -124,3 +124,5 @@ STATIC_URL = 'static/'
|
|||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
FIXTURE_DIRS = ['don_confiao/tests/Fixtures']
|
||||||
|
Loading…
Reference in New Issue
Block a user