You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
377 lines
14 KiB
377 lines
14 KiB
from django.shortcuts import render,redirect,get_object_or_404
|
|
from django.template.loader import get_template
|
|
from django.http import HttpResponse
|
|
from django.contrib import messages
|
|
from django.contrib.auth.forms import AuthenticationForm
|
|
from django.contrib.auth import login, logout, authenticate
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.db.models import Avg, Sum
|
|
from decimal import Decimal
|
|
from django.db.models import F
|
|
from .forms import formulario_proveedor,formulario_bodega, formulario_tipo, formulario_articulo,formilario_inventario,VentaForm
|
|
from .models import proveedor, bodega, tipo_articulo, articulo,inventario,tipo_inv_movimiento,movimiento_inventario,Venta
|
|
|
|
# Create your views here.
|
|
def base(request):
|
|
return render(request, 'index.html')
|
|
|
|
|
|
def graficos_view(request):
|
|
# 1. Ventas por bodega
|
|
ventas_por_bodega = (
|
|
Venta.objects.values("bodega__nombre_bodega")
|
|
.annotate(total_ventas=Sum("total"))
|
|
)
|
|
for item in ventas_por_bodega:
|
|
item["total_ventas"] = float(Decimal(item["total_ventas"] or 0)) # Convertir a float
|
|
|
|
# 2. Inventario total por artículo
|
|
inventario_total = (
|
|
inventario.objects.values("articulo__nombre_articulo")
|
|
.annotate(total=Sum("cantidad"))
|
|
)
|
|
|
|
# 3. Ventas por artículo
|
|
ventas_por_articulo = (
|
|
Venta.objects.values("articulo__nombre_articulo")
|
|
.annotate(total=Sum("cantidad"))
|
|
)
|
|
|
|
# 4. Comparación de precios de artículos
|
|
precios_articulos = list(articulo.objects.values(
|
|
"nombre_articulo",
|
|
"precio_compra",
|
|
"precio_venta",
|
|
))
|
|
for item in precios_articulos:
|
|
item["precio_compra"] = float(Decimal(item["precio_compra"] or 0)) # Convertir a float
|
|
item["precio_venta"] = float(Decimal(item["precio_venta"] or 0)) # Convertir a float
|
|
|
|
# Calcular el total de ventas
|
|
total_ventas = Venta.objects.aggregate(total_ventas=Sum('total'))['total_ventas'] or Decimal(0)
|
|
|
|
# Calcular el total de productos en inventario
|
|
total_productos_en_inventario = inventario.objects.aggregate(total_productos=Sum('cantidad'))['total_productos'] or 0
|
|
|
|
# Calcular el total de artículos vendidos
|
|
total_articulos_vendidos = ventas_por_articulo.aggregate(total_vendidos=Sum('total'))['total_vendidos'] or 0
|
|
|
|
# Calcular el total de proveedores
|
|
total_proveedores = proveedor.objects.count()
|
|
|
|
context = {
|
|
"ventas_por_bodega": list(ventas_por_bodega),
|
|
"inventario_total": list(inventario_total),
|
|
"ventas_por_articulo": list(ventas_por_articulo),
|
|
"precios_articulos": precios_articulos,
|
|
"total_ventas": float(total_ventas), # Sumar todas las ventas totales
|
|
"total_productos_en_inventario": total_productos_en_inventario, # Número total de productos en inventario
|
|
"total_articulos_vendidos": total_articulos_vendidos, # Total de unidades vendidas
|
|
"total_proveedores": total_proveedores, # Número de proveedores
|
|
}
|
|
|
|
return render(request, "index.html", context)
|
|
|
|
def signin(request):
|
|
if request.method == 'GET':
|
|
return render ( request, 'signin.html',{
|
|
'form': AuthenticationForm
|
|
})
|
|
else:
|
|
user=authenticate(request, username=request.POST['username'], password=request.POST['password'])
|
|
if user is None:
|
|
return render ( request, 'signin.html',{
|
|
'form': AuthenticationForm ,
|
|
'error': 'Username or password is incorrect'
|
|
})
|
|
else:
|
|
login(request, user)
|
|
return redirect('home')
|
|
|
|
@login_required
|
|
def signout(request):
|
|
logout(request)
|
|
return redirect('home')
|
|
|
|
@login_required
|
|
def proveedor_registro(request):
|
|
if request.method=='GET':
|
|
return render(request, 'proveedor_nuevo.html',{
|
|
'form': formulario_proveedor
|
|
})
|
|
else:
|
|
try:
|
|
form = formulario_proveedor (request.POST)
|
|
new_proveedor=form.save(commit=False)
|
|
new_proveedor.save()
|
|
return redirect('proveedor')
|
|
except ValueError:
|
|
return render(request, 'proveedor_nuevo.html',{
|
|
'form': formulario_proveedor,
|
|
'error':'porfavor ingrese bien los datos'
|
|
})
|
|
|
|
@login_required
|
|
def proveedor_lista(request):
|
|
persona = proveedor.objects.all
|
|
return render(request,"proveedor_registro.html", {'persona':persona})
|
|
|
|
@login_required
|
|
def Proveedor_update(request,task_id):
|
|
if request.method == 'GET':
|
|
tarea = get_object_or_404 (proveedor, pk=task_id)
|
|
form = formulario_proveedor(instance=tarea)
|
|
return render(request, 'proveedor_update.html',{'tasks':tarea, 'form':form} )
|
|
else:
|
|
try:
|
|
tarea=get_object_or_404(proveedor,pk=task_id)
|
|
form = formulario_proveedor(request.POST, instance=tarea)
|
|
form.save()
|
|
return redirect('proveedor')
|
|
except ValueError:
|
|
return render(request, 'proveedor_update.html',{'tasks':tarea, 'form':form, 'error': 'error updating task'} )
|
|
|
|
@login_required
|
|
def bodega_registro(request):
|
|
if request.method=='GET':
|
|
return render(request, 'bodega_nuevo.html',{
|
|
'form': formulario_bodega
|
|
})
|
|
else:
|
|
try:
|
|
form = formulario_bodega (request.POST)
|
|
new_bodega=form.save(commit=False)
|
|
new_bodega.save()
|
|
return redirect('bodega_vista')
|
|
except ValueError:
|
|
return render(request, 'bodega_nuevo.html',{
|
|
'form': formulario_bodega,
|
|
'error':'Please provide valid data'
|
|
})
|
|
|
|
@login_required
|
|
def bodega_vista(request):
|
|
persona = bodega.objects.all
|
|
return render(request,"bodega_registro.html", {'persona':persona})
|
|
|
|
@login_required
|
|
def bodega_update(request,task_id):
|
|
if request.method == 'GET':
|
|
tarea = get_object_or_404 (bodega, pk=task_id)
|
|
form = formulario_bodega(instance=tarea)
|
|
return render(request, 'bodega_update.html',{'tasks':tarea, 'form':form} )
|
|
else:
|
|
try:
|
|
tarea=get_object_or_404(bodega,pk=task_id)
|
|
form = formulario_bodega(request.POST, instance=tarea)
|
|
form.save()
|
|
return redirect('bodega_vista')
|
|
except ValueError:
|
|
return render(request, 'bodega_update.html',{'tasks':tarea, 'form':form, 'error': 'error updating task'} )
|
|
|
|
@login_required
|
|
def tipo_registro(request):
|
|
if request.method=='GET':
|
|
return render(request, 'tipo_articulo_nuevo.html',{
|
|
'form': formulario_tipo
|
|
})
|
|
else:
|
|
try:
|
|
form = formulario_tipo (request.POST)
|
|
new_tipo=form.save(commit=False)
|
|
new_tipo.save()
|
|
return redirect('tipo_vista')
|
|
|
|
except ValueError:
|
|
return render(request, 'tipo_articulo_nuevo.html',{
|
|
'form': formulario_tipo,
|
|
'error':'Please provide valid data'
|
|
})
|
|
|
|
@login_required
|
|
def tipo_vista(request):
|
|
persona = tipo_articulo.objects.all
|
|
return render(request,"tipo_articulo_registro.html", {'persona':persona})
|
|
|
|
@login_required
|
|
def tipo_update(request,task_id):
|
|
if request.method == 'GET':
|
|
tarea = get_object_or_404 (tipo_articulo, pk=task_id)
|
|
form = formulario_tipo(instance=tarea)
|
|
return render(request, 'tipo_articulo_update.html',{'tasks':tarea, 'form':form} )
|
|
else:
|
|
try:
|
|
tarea=get_object_or_404(tipo_articulo,pk=task_id)
|
|
form = formulario_tipo(request.POST, instance=tarea)
|
|
form.save()
|
|
return redirect('tipo_vista')
|
|
except ValueError:
|
|
return render(request, 'tipo_articulo_update.html',{'tasks':tarea, 'form':form, 'error': 'error updating task'} )
|
|
|
|
@login_required
|
|
def articulo_registro(request):
|
|
if request.method=='GET':
|
|
return render(request, 'articulo_nuevo.html',{
|
|
'form': formulario_articulo
|
|
})
|
|
else:
|
|
try:
|
|
form = formulario_articulo (request.POST)
|
|
form.save()
|
|
return redirect('articulo_vista')
|
|
|
|
except ValueError:
|
|
return render(request, 'articulo_nuevo.html',{
|
|
'form': formulario_articulo,
|
|
'error':'Please provide valid data'
|
|
})
|
|
|
|
@login_required
|
|
def articulo_vista(request):
|
|
persona = articulo.objects.select_related('tipo_articulo','proveedor').all()
|
|
return render(request,"articulo_registro.html", {'persona':persona})
|
|
|
|
@login_required
|
|
def articulo_update(request,task_id):
|
|
if request.method == 'GET':
|
|
tarea = get_object_or_404 (articulo, pk=task_id)
|
|
form = formulario_articulo(instance=tarea)
|
|
return render(request, 'articulo_update.html',{'tasks':tarea, 'form':form} )
|
|
else:
|
|
try:
|
|
tarea=get_object_or_404(articulo,pk=task_id)
|
|
form = formulario_articulo(request.POST, instance=tarea)
|
|
form.save()
|
|
return redirect('articulo_vista')
|
|
except ValueError:
|
|
return render(request, 'articulo_update.html',{'tasks':tarea, 'form':form, 'error': 'error updating'} )
|
|
|
|
@login_required
|
|
def inventario_registro(request):
|
|
if request.method=='GET':
|
|
return render(request, 'inventario_nuevo.html',{
|
|
'form': formilario_inventario
|
|
})
|
|
else:
|
|
try:
|
|
form = formilario_inventario (request.POST)
|
|
form.save()
|
|
form = formilario_inventario ()
|
|
return render(request, 'inventario_nuevo.html',{
|
|
'form': formilario_inventario,
|
|
'mensaje':'Please provide valid data'
|
|
})
|
|
except ValueError:
|
|
return render(request, 'inventario_nuevo.html',{
|
|
'form': formilario_inventario,
|
|
'error':'Please provide valid data'
|
|
})
|
|
|
|
@login_required
|
|
def inventario_vista(request):
|
|
persona = inventario.objects.select_related('articulo','bodega').all()
|
|
return render(request,"inventario_registro.html", {'persona':persona})
|
|
|
|
def registrar_movimiento_y_actualizar_inventario(movimiento_data):
|
|
|
|
"""
|
|
Registra un movimiento de inventario y actualiza el inventario relacionado.
|
|
"""
|
|
try:
|
|
with transaction.atomic():
|
|
# Registrar el movimiento de inventario
|
|
movimiento = movimiento_inventario.objects.create(
|
|
articulo=movimiento_data['articulo'],
|
|
bodega=movimiento_data['bodega'],
|
|
tipo_inventario=movimiento_data['tipo_inventario'],
|
|
cantidad=movimiento_data['cantidad'],
|
|
observaciones=movimiento_data.get('observaciones', '')
|
|
)
|
|
|
|
# Buscar o crear el inventario correspondiente
|
|
inventario_obj, created = inventario.objects.get_or_create(
|
|
articulo=movimiento.articulo,
|
|
bodega=movimiento.bodega,
|
|
defaults={'cantidad': 0}
|
|
)
|
|
|
|
# Comprobación y actualización según el tipo de movimiento
|
|
if movimiento.tipo_inventario.id == 1:
|
|
inventario_obj.cantidad += movimiento.cantidad
|
|
elif movimiento.tipo_inventario.id == 2:
|
|
if inventario_obj.cantidad < movimiento.cantidad:
|
|
raise ValueError(
|
|
f"No hay suficiente stock. Disponible: {inventario_obj.cantidad}, solicitado: {movimiento.cantidad}"
|
|
)
|
|
inventario_obj.cantidad -= movimiento.cantidad
|
|
|
|
# Guardar los cambios en el inventario
|
|
inventario_obj.save()
|
|
|
|
return movimiento, inventario_obj
|
|
|
|
except Exception as e:
|
|
raise ValueError(f"Error al registrar movimiento y actualizar inventario: {str(e)}")
|
|
|
|
|
|
def nueva_venta(request):
|
|
if request.method == 'POST':
|
|
form = VentaForm(request.POST)
|
|
if form.is_valid():
|
|
venta = form.save(commit=False)
|
|
|
|
# Verificar si el artículo existe en la bodega seleccionada
|
|
try:
|
|
inventario_item = inventario.objects.get(
|
|
bodega=venta.bodega,
|
|
articulo=venta.articulo
|
|
)
|
|
except inventario.DoesNotExist:
|
|
form.add_error('articulo', 'El artículo no existe en la bodega seleccionada.')
|
|
return render(request, 'nueva_venta.html', {'form': form})
|
|
|
|
# Validar que haya suficiente cantidad en el inventario
|
|
if inventario_item.cantidad >= venta.cantidad:
|
|
# Guardar la venta
|
|
venta.save()
|
|
|
|
return redirect('lista_ventas') # Redirigir al listado de ventas
|
|
else:
|
|
form.add_error('cantidad', 'Cantidad en inventario insuficiente.')
|
|
else:
|
|
form = VentaForm()
|
|
|
|
return render(request, 'nueva_venta.html', {'form': form})
|
|
|
|
def registrar_movimiento(request):
|
|
"""
|
|
Vista para registrar un nuevo movimiento de inventario.
|
|
"""
|
|
if request.method == 'POST':
|
|
form = formilario_inventario(request.POST)
|
|
if form.is_valid():
|
|
movimiento_data = form.cleaned_data
|
|
try:
|
|
movimiento, inventario_obj = registrar_movimiento_y_actualizar_inventario(movimiento_data)
|
|
return redirect('vista_inventario_mov') # Redirigir a una página de éxito
|
|
except ValueError as e:
|
|
return render(request, 'inventario_nuevo.html', {
|
|
'form': form,
|
|
'error': str(e)
|
|
})
|
|
else:
|
|
form = formilario_inventario()
|
|
|
|
return render(request, 'inventario_nuevo.html', {'form': form})
|
|
|
|
@login_required
|
|
def vista_inventario_mov(request):
|
|
persona = movimiento_inventario.objects.select_related('articulo','bodega','tipo_inventario').all()
|
|
return render(request,"mov_inventario_registro.html", {'persona':persona})
|
|
|
|
def lista_ventas(request):
|
|
ventas = Venta.objects.all()
|
|
return render(request, 'ventas.html', {'ventas': ventas})
|
|
|
|
|