245 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from django.shortcuts import render
 | |
| from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
 | |
| from django.views.generic import ListView
 | |
| from django.db import transaction
 | |
| 
 | |
| from .models import (
 | |
|     Sale, SaleLine, Product, Customer, ProductCategory, Payment, PaymentMethods, ReconciliationJar)
 | |
| from .forms import (
 | |
|     ImportProductsForm,
 | |
|     ImportCustomersForm,
 | |
|     PurchaseForm,
 | |
|     SaleLineFormSet,
 | |
|     PurchaseSummaryForm)
 | |
| 
 | |
| import csv
 | |
| import io
 | |
| import json
 | |
| from decimal import Decimal
 | |
| 
 | |
| 
 | |
| class DecimalEncoder(json.JSONEncoder):
 | |
|     def default(self, obj):
 | |
|         if isinstance(obj, Decimal):
 | |
|             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)
 | |
|         line_formset = SaleLineFormSet(request.POST)
 | |
|         sale_summary_form = PurchaseSummaryForm(request.POST)
 | |
|         forms_are_valid = all([
 | |
|             sale_form.is_valid(),
 | |
|             line_formset.is_valid(),
 | |
|             sale_summary_form.is_valid()
 | |
|         ])
 | |
|         payment_method = request.POST.get('payment_method')
 | |
|         valid_payment_methods = [PaymentMethods.CASH]
 | |
|         valid_payment_method = payment_method in valid_payment_methods
 | |
|         if forms_are_valid:
 | |
|             with transaction.atomic():
 | |
|                 sale = sale_form.save()
 | |
|                 line_formset.instance = sale
 | |
|                 line_formset.save()
 | |
|                 Payment.total_payment_from_sale(
 | |
|                     payment_method,
 | |
|                     sale
 | |
|                 )
 | |
|             return HttpResponseRedirect("compras")
 | |
|     else:
 | |
|         sale_form = PurchaseForm()
 | |
|         line_formset = SaleLineFormSet()
 | |
|         sale_summary_form = PurchaseSummaryForm()
 | |
|     return render(
 | |
|         request,
 | |
|         'don_confiao/purchase.html',
 | |
|         {
 | |
|             'sale_form': sale_form,
 | |
|             'linea_formset': line_formset,
 | |
|             'summary_form': sale_summary_form,
 | |
|             'list_products': json.dumps(Product.to_list(), cls=DecimalEncoder),
 | |
|         }
 | |
|     )
 | |
| 
 | |
| 
 | |
| def purchases(request):
 | |
|     purchases = Sale.objects.all()
 | |
|     context = {
 | |
|         "purchases": purchases,
 | |
|     }
 | |
|     return render(request, 'don_confiao/purchases.html', context)
 | |
| 
 | |
| 
 | |
| def products(request):
 | |
|     return JsonResponse(Product.to_list(), safe=False)
 | |
| 
 | |
| 
 | |
| def import_products(request):
 | |
|     if request.method == "POST":
 | |
|         form = ImportProductsForm(request.POST, request.FILES)
 | |
|         if form.is_valid():
 | |
|             handle_import_products_file(request.FILES["csv_file"])
 | |
|             return HttpResponseRedirect("productos")
 | |
|     else:
 | |
|         form = ImportProductsForm()
 | |
|     return render(
 | |
|         request,
 | |
|         "don_confiao/import_products.html",
 | |
|         {'form': form}
 | |
|     )
 | |
| 
 | |
| 
 | |
| def import_customers(request):
 | |
|     if request.method == "POST":
 | |
|         form = ImportCustomersForm(request.POST, request.FILES)
 | |
|         if form.is_valid():
 | |
|             handle_import_customers_file(request.FILES["csv_file"])
 | |
|             return HttpResponseRedirect("productos")
 | |
|     else:
 | |
|         form = ImportCustomersForm()
 | |
|     return render(
 | |
|         request,
 | |
|         "don_confiao/import_customers.html",
 | |
|         {'form': form}
 | |
|     )
 | |
| 
 | |
| 
 | |
| def reconciliations(request):
 | |
|     return HttpResponse('<h1>Reconciliaciones</h1>')
 | |
| 
 | |
| 
 | |
| def purchase_summary(request, id):
 | |
|     purchase = Sale.objects.get(pk=id)
 | |
|     return render(
 | |
|         request,
 | |
|         "don_confiao/purchase_summary.html",
 | |
|         {
 | |
|             "purchase": purchase
 | |
|         }
 | |
|     )
 | |
| 
 | |
| 
 | |
| def _categories_from_csv_string(categories_string, separator="&"):
 | |
|     categories = categories_string.split(separator)
 | |
|     clean_categories = [c.strip() for c in categories]
 | |
|     return [_category_from_name(category) for category in clean_categories]
 | |
| 
 | |
| 
 | |
| def _category_from_name(name):
 | |
|     return ProductCategory.objects.get_or_create(name=name)[0]
 | |
| 
 | |
| 
 | |
| def handle_import_products_file(csv_file):
 | |
|     data = io.StringIO(csv_file.read().decode('utf-8'))
 | |
|     reader = csv.DictReader(data, quotechar='"')
 | |
|     for row in reader:
 | |
|         product, created = Product.objects.update_or_create(
 | |
|             name=row['producto'],
 | |
|             defaults={
 | |
|                 'price': row['precio'],
 | |
|                 'measuring_unit': row['unidad']
 | |
|             }
 | |
|         )
 | |
|         categories = _categories_from_csv_string(row["categorias"])
 | |
|         product.categories.clear()
 | |
|         for category in categories:
 | |
|             product.categories.add(category)
 | |
| 
 | |
| def handle_import_customers_file(csv_file):
 | |
|     data = io.StringIO(csv_file.read().decode('utf-8'))
 | |
|     reader = csv.DictReader(data, quotechar='"')
 | |
|     for row in reader:
 | |
|         customer, created = Customer.objects.update_or_create(
 | |
|             name=row['nombre'],
 | |
|             defaults={
 | |
|                 'email': row['correo'],
 | |
|                 'phone': row['telefono']
 | |
|             }
 | |
|         )
 | |
| 
 | |
| def sales_to_tryton_csv(sales):
 | |
|     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"
 | |
|     ]
 | |
| 
 | |
|     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.strftime('%Y-%m-%d'),
 | |
|             "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":
 | |
|         response = HttpResponse(content_type='text/csv')
 | |
|         response['Content-Disposition'] = "attachment; filename=sales.csv"
 | |
|         sales = Sale.objects.all()
 | |
|         csv_data = sales_to_tryton_csv(sales)
 | |
|         writer = csv.writer(response)
 | |
|         for row in csv_data:
 | |
|             writer.writerow(row)
 | |
| 
 | |
|         return response
 | |
| 
 | |
| 
 | |
| class ProductListView(ListView):
 | |
|     model = Product
 | |
|     template_model = 'don_confiao/product_list.html'
 | |
| 
 | |
|     def get_queryset(self):
 | |
|         name = self.request.GET.get('name')
 | |
|         if name:
 | |
|             return Product.objects.filter(name__icontains=name)
 | |
|         return Product.objects.all()
 |