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 .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) new_proveedor=form.save(commit=False) new_proveedor.save() messages.success(request, 'ingreso exitoso') 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) 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})