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,
|
|
"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()
|