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})