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.
338 lines
13 KiB
338 lines
13 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.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 .forms import formulario_proveedor,formulario_bodega, formulario_tipo, formulario_articulo,formilario_inventario
|
|
from .models import proveedor, bodega, tipo_articulo, articulo,inventario,tipo_inv_movimiento,movimiento_inventario
|
|
|
|
# Create your views here.
|
|
def base(request):
|
|
return render(request, 'index.html')
|
|
|
|
def generar_grafico_chartjs(request):
|
|
# Gráfico de Pastel: Cantidad por tipo de artículo
|
|
tipos_articulo = tipo_articulo.objects.all()
|
|
tipos_nombres = [t.tipo_articulo for t in tipos_articulo]
|
|
cantidades_por_tipo = [articulo.objects.filter(tipo_articulo=t).count() for t in tipos_articulo]
|
|
|
|
# Gráfico de Barras: Cantidad de artículos por bodega
|
|
bodegas = bodega.objects.all()
|
|
bodegas_nombres = [b.nombre_bodega for b in bodegas]
|
|
cantidades_por_bodega = [inventario.objects.filter(bodega=b).count() for b in bodegas]
|
|
|
|
# Gráfico de Línea: Movimientos en el tiempo
|
|
|
|
tipos_movimientos = tipo_inv_movimiento.objects.all()
|
|
nombres_tipos = [mov.tipo_movimiento for mov in tipos_movimientos]
|
|
|
|
# Obtener la cantidad total movida para cada tipo de movimiento
|
|
cantidades_por_tipos = [
|
|
movimiento_inventario.objects.filter(tipo_inventario=mov).aggregate(total=Sum('cantidad'))['total'] or 0
|
|
for mov in tipos_movimientos
|
|
]
|
|
tipos_articulo_prom = [t.tipo_articulo for t in tipos_articulo]
|
|
|
|
precios_promedio = [
|
|
float(inventario.objects.filter(articulo__tipo_articulo=t).aggregate(avg=Avg('precio'))['avg'] or 0)
|
|
for t in tipos_articulo
|
|
]
|
|
|
|
context = {
|
|
'tipos_articulo': tipos_nombres,
|
|
'cantidades_por_tipo': cantidades_por_tipo,
|
|
'bodegas': bodegas_nombres,
|
|
'cantidades_por_bodega': cantidades_por_bodega,
|
|
'tipos_articulo_prom': tipos_articulo_prom,
|
|
'precios_promedio': precios_promedio,
|
|
'nombres_tipos': nombres_tipos,
|
|
'cantidades_por_tipos': cantidades_por_tipos,
|
|
}
|
|
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)
|
|
form.save()
|
|
form = formulario_proveedor ()
|
|
return render(request, 'proveedor_nuevo.html',{
|
|
'form': formulario_proveedor,
|
|
'mensaje':'Please provide valid data'
|
|
})
|
|
except ValueError:
|
|
return render(request, 'proveedor_nuevo.html',{
|
|
'form': formulario_proveedor,
|
|
'error':'Please provide valid data'
|
|
})
|
|
|
|
@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)
|
|
form.save()
|
|
form = formulario_bodega ()
|
|
return render(request, 'bodega_nuevo.html',{
|
|
'form': formulario_bodega,
|
|
'mensaje':'Please provide valid data'
|
|
})
|
|
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)
|
|
form.save()
|
|
form = formulario_tipo ()
|
|
return render(request, 'tipo_articulo_nuevo.html',{
|
|
'form': formulario_tipo,
|
|
'mensaje':'Please provide valid data'
|
|
})
|
|
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()
|
|
form = formulario_articulo ()
|
|
return redirect('articulo_registro')
|
|
|
|
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'],
|
|
precio=movimiento_data['precio'],
|
|
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, 'precio': movimiento.precio}
|
|
)
|
|
|
|
# Actualizar stock según el tipo de movimiento
|
|
if movimiento.tipo_inventario.id == 1: # Asegúrate de que 'nombre' sea un campo válido
|
|
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
|
|
|
|
# Actualizar el precio en Inventario si es necesario
|
|
if inventario_obj.precio != movimiento.precio:
|
|
inventario_obj.precio = movimiento.precio
|
|
|
|
# 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 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('registrar_movimiento') # 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})
|
|
|
|
|