diseños v2, precios en articulos y sector de ventas/ reportes borrados para mejorar e actualizar

main
Francisco_Borja 1 year ago
parent 67827f4bbc
commit 317b2a0427
  1. BIN
      Inventario/__pycache__/forms.cpython-313.pyc
  2. BIN
      Inventario/__pycache__/models.cpython-313.pyc
  3. BIN
      Inventario/__pycache__/views.cpython-313.pyc
  4. 43
      Inventario/forms.py
  5. 50
      Inventario/migrations/0004_remove_inventario_precio_and_more.py
  6. BIN
      Inventario/migrations/__pycache__/0004_remove_inventario_precio_and_more.cpython-313.pyc
  7. 55
      Inventario/models.py
  8. 18
      Inventario/templates/Base.html
  9. 29
      Inventario/templates/articulo_nuevo.html
  10. 32
      Inventario/templates/articulo_registro.html
  11. 15
      Inventario/templates/articulo_update.html
  12. 29
      Inventario/templates/bodega_nuevo.html
  13. 40
      Inventario/templates/bodega_registro.html
  14. 37
      Inventario/templates/bodega_update.html
  15. 172
      Inventario/templates/index.html
  16. 32
      Inventario/templates/inventario_nuevo.html
  17. 38
      Inventario/templates/inventario_registro.html
  18. 24
      Inventario/templates/mov_inventario_registro.html
  19. 30
      Inventario/templates/nueva_venta.html
  20. 33
      Inventario/templates/proveedor_nuevo.html
  21. 18
      Inventario/templates/proveedor_registro.html
  22. 30
      Inventario/templates/proveedor_update.html
  23. 30
      Inventario/templates/tipo_articulo_nuevo.html
  24. 35
      Inventario/templates/tipo_articulo_registro.html
  25. 30
      Inventario/templates/tipo_articulo_update.html
  26. 54
      Inventario/templates/ventas.html
  27. 114
      Inventario/views.py
  28. BIN
      TiendAlfa/__pycache__/urls.cpython-313.pyc
  29. 6
      TiendAlfa/urls.py

@ -1,5 +1,5 @@
from django import forms
from .models import proveedor, bodega, tipo_articulo, articulo,inventario,tipo_inv_movimiento
from .models import proveedor, bodega, tipo_articulo, articulo,inventario,tipo_inv_movimiento,Venta
class formulario_proveedor(forms.ModelForm):
class Meta:
@ -36,11 +36,23 @@ class formulario_articulo(forms.ModelForm):
tipo_articulo=forms.ModelChoiceField(queryset=tipo_articulo.objects.all(),
empty_label="Selecciona un tipo de articulo",
widget=forms.Select(attrs={'class': 'btn btn-secondary dropdown-toggle', 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false'}),
label="tipo_articulo")
label="Tipo de articulo")
proveedor=forms.ModelChoiceField(queryset=proveedor.objects.all(),
empty_label="Selecciona un proveedor",
widget=forms.Select(attrs={'class': 'btn btn-secondary dropdown-toggle ', 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false'}),
label="proveedor")
label="Proveedor")
precio_compra=forms.DecimalField(
label="Precio de compra",
max_digits=10,
decimal_places=2,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Escribe un decimal'}))
precio_venta=forms.DecimalField(
label="Precio de venta",
max_digits=10,
decimal_places=2,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Escribe un decimal'}))
class Meta:
model = articulo
fields = '__all__'
@ -48,6 +60,7 @@ class formulario_articulo(forms.ModelForm):
'nombre_articulo': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'escriba el nombre del articulo'}),
'medida': forms.TextInput(attrs={'class':'form-control','placeholder':'medida del producto lts, cm, etc'}),
'descripcion': forms.Textarea(attrs={'class':'form-control','placeholder':'describa el producto','rows':'5'}),
}
class formilario_inventarios(forms.ModelForm):
@ -65,7 +78,6 @@ class formilario_inventarios(forms.ModelForm):
fields = '__all__'
widgets={
'cantidad': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'Cantidad de productos','oninput':'permitirSoloNumeros(this)',}),
'precio': forms.NumberInput(attrs={'class':'form-control','placeholder':'Ej: 99.99','step': '0.01','min':'0','max':'10000',}),
}
class formilario_inventario(forms.ModelForm):
@ -93,7 +105,28 @@ class formilario_inventario(forms.ModelForm):
fields = '__all__'
widgets={
'fecha': forms.DateInput(attrs={'type': 'date','class': 'form-control','placeholder': 'Seleccione una fecha'}),
'precio': forms.NumberInput(attrs={'class':'form-control','placeholder':'Ej: 99.99','step': '0.01','min':'0','max':'10000',}),
'cantidad': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'Cantidad de productos','oninput':'permitirSoloNumeros(this)',}),
'observacion': forms.Textarea(attrs={'class':'form-control','placeholder':'observacion','rows':'5'}),
}
class VentaForm(forms.ModelForm):
articulo=forms.ModelChoiceField(queryset=articulo.objects.all(),
empty_label="selecciones un articulo",
widget=forms.Select(attrs={'class': 'btn btn-secondary dropdown-toggle', 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false'}),
label="articulo")
bodega=forms.ModelChoiceField(queryset=bodega.objects.all(),
empty_label="Selecciona una bodega",
widget=forms.Select(attrs={'class': 'btn btn-secondary dropdown-toggle ', 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false'}),
label="bodega")
cantidad=forms.DecimalField(
label="cantidad",
max_digits=10,
decimal_places=2,
widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Escribe un decimal'}))
class Meta:
model = Venta
fields = ['bodega', 'articulo', 'cantidad', 'observaciones']
widgets={
'observaciones': forms.Textarea(attrs={'class':'form-control','placeholder':'describa el producto','rows':'5'}),
}

@ -0,0 +1,50 @@
# Generated by Django 5.1.4 on 2024-12-17 22:48
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('Inventario', '0003_remove_articulo_codigo_articulo_articulo_medida'),
]
operations = [
migrations.RemoveField(
model_name='inventario',
name='precio',
),
migrations.RemoveField(
model_name='movimiento_inventario',
name='precio',
),
migrations.AddField(
model_name='articulo',
name='precio_compra',
field=models.DecimalField(decimal_places=2, max_digits=10, null=True),
),
migrations.AddField(
model_name='articulo',
name='precio_venta',
field=models.DecimalField(decimal_places=2, max_digits=10, null=True),
),
migrations.AlterField(
model_name='movimiento_inventario',
name='fecha',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.CreateModel(
name='Venta',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fecha', models.DateTimeField(auto_now_add=True)),
('cantidad', models.PositiveIntegerField()),
('precio_unitario', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('total', models.DecimalField(blank=True, decimal_places=2, max_digits=12)),
('observaciones', models.TextField(blank=True)),
('articulo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Inventario.articulo')),
('bodega', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Inventario.bodega')),
],
),
]

@ -1,5 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
from django.db import transaction
# Create your models here.
@ -34,6 +36,8 @@ class articulo(models.Model):
nombre_articulo=models.CharField(max_length=100)
medida = models.CharField(max_length=100, blank=True, null=True)
descripcion = models.TextField(blank=True)
precio_compra=models.DecimalField( max_digits=10, decimal_places=2, null=True)
precio_venta=models.DecimalField( max_digits=10, decimal_places=2, null=True)
proveedor = models.ForeignKey(proveedor, on_delete=models.CASCADE)
tipo_articulo=models.ForeignKey(tipo_articulo, on_delete=models.CASCADE)
def __str__(self):
@ -44,15 +48,60 @@ class inventario(models.Model):
bodega=models.ForeignKey(bodega, on_delete=models.CASCADE)
articulo=models.ForeignKey(articulo, on_delete=models.CASCADE)
cantidad=models.IntegerField(null=True)
precio=models.DecimalField( max_digits=10, decimal_places=2)
class Venta(models.Model):
fecha = models.DateTimeField(auto_now_add=True)
bodega = models.ForeignKey(bodega, on_delete=models.CASCADE)
articulo = models.ForeignKey(articulo, on_delete=models.CASCADE)
cantidad = models.PositiveIntegerField()
precio_unitario = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
total = models.DecimalField(max_digits=12, decimal_places=2, blank=True)
observaciones = models.TextField(blank=True)
def save(self, *args, **kwargs):
# Asignar el precio de venta del artículo si no se ha definido
if not self.precio_unitario:
self.precio_unitario = self.articulo.precio_venta or 0
# Calcular el total antes de guardar
if not self.total:
self.total = self.cantidad * self.precio_unitario
# Usar una transacción atómica para asegurar que todo suceda de forma consistente
with transaction.atomic():
# Guardar la venta primero
super(Venta, self).save(*args, **kwargs)
# Obtener el artículo y bodega para verificar el inventario
inventario_item = inventario.objects.get(bodega=self.bodega, articulo=self.articulo)
# Verificar que haya suficiente cantidad en el inventario
if inventario_item.cantidad >= self.cantidad:
# Crear el movimiento de inventario (salida)
tipo_salida = tipo_inv_movimiento.objects.get(tipo_movimiento="Salida")
movimiento = movimiento_inventario(
tipo_inventario=tipo_salida,
bodega=self.bodega,
articulo=self.articulo,
cantidad=self.cantidad,
observaciones=f"Salida por venta. {self.observaciones}"
)
movimiento.save()
# Actualizar el inventario después de la venta
inventario_item.cantidad -= self.cantidad
inventario_item.save()
else:
# Si no hay suficiente inventario, lanzar una excepción
raise ValueError("No hay suficiente inventario para realizar esta venta.")
def __str__(self):
return f"Venta de {self.articulo.nombre_articulo} - {self.cantidad} unidades"
class movimiento_inventario(models.Model):
fecha=models.DateTimeField(null=True)
fecha=models.DateTimeField(null=True, auto_now_add=True)
tipo_inventario=models.ForeignKey(tipo_inv_movimiento,on_delete=models.CASCADE)
bodega=models.ForeignKey(bodega, on_delete=models.CASCADE)
articulo=models.ForeignKey(articulo, on_delete=models.CASCADE)
cantidad=models.IntegerField(null=True)
precio=models.DecimalField(max_digits=10, decimal_places=2)
observaciones=models.TextField(blank=True)

@ -12,13 +12,13 @@
<nav class="navbar bg-dark navbar-dark">
<div class="container-fluid ">
<a class="navbar-brand " href="/">Tienda Dany</a>
<button class="navbar-toggler " type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar" aria-controls="offcanvasNavbar" aria-label="Toggle navigation">
<button class="navbar-toggler " type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasResponsive" aria-controls="offcanvasResponsive" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="offcanvas offcanvas-end bg-dark navbar-dark" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel">
<div class="offcanvas offcanvas-end bg-dark navbar-dark" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title"style="color:white;" id="offcanvasNavbarLabel">Bienvenido {{user.username}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#offcanvasResponsive" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
@ -75,6 +75,18 @@
<li>
<hr class="dropdown-divider">
</li>
<li class="nav-item dropdown ">
<a class="nav-link dropdown-toggle " role="button" data-bs-toggle="dropdown" aria-expanded="false">
Ventas
</a>
<ul class="dropdown-menu dropdown-menu-dark">
<li><a class="dropdown-item" href="{% url 'lista_ventas' %}">Lista de ventas</a></li>
<li><a class="dropdown-item" href="{% url 'nueva_venta' %}">Nueva venta</li>
</ul>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">logout</a>
</li>

@ -7,34 +7,19 @@
<div class="col-md-8 offset-md-2 mt-4">
<form action="/articulo/crear/" method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'articulo_vista' %}"><- volver</a>
<h3 class="col-5">Registro articulo</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Registrar nuevo articulo</h4>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% csrf_token %}
{{form.as_p}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">Crear nuevo articulo</button>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'articulo_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Crear nuevo articulo</button>
</div>
</div>
</div>
</form>

@ -6,19 +6,21 @@
<div class="col-md-10 offset-md-1 mt-4">
<form action="/articulo/" method="POST">
<div class="card-header row col-12 justify-content-end mb-2 pr-0 mt-2">
<h3 class="col-md-4">Vista articulo</h3>
<a class="btn btn-success col-md-3" href="{% url 'articulo_registro' %}">Nuevo articulo</a>
<h3 class="text-center">Tabla de articulos</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">nombre del articulo</th>
<th scope="col">medida</th>
<th scope="col">descripcion</th>
<th scope="col">tipo_articulo</th>
<th scope="col">proveedors</th>
<th scope="col">actualizar</th>
<th scope="col">Nombre del articulo</th>
<th scope="col">Medida del articulo</th>
<th scope="col">Descripcion</th>
<th scope="col">Tipo del articulo</th>
<th scope="col">Proveedor</th>
<th scope="col">Precio de compra</th>
<th scope="col">Precio de venta</th>
<th scope="col">ACTUALIZAR</th>
</tr>
</thead>
@ -31,14 +33,24 @@
<td> {{ articulo.descripcion }} </td>
<td> {{ articulo.tipo_articulo.tipo_articulo }} </td>
<td> {{ articulo.proveedor.nombre_proveedor }} </td>
<td> <a class="btn btn-warning" href="{% url 'articulo_update' articulo.id %}">Editar</a> </td>
<td> {{ articulo.precio_compra }} </td>
<td> {{ articulo.precio_venta }} </td>
<td class="text-center"> <a class="btn btn-secondary" href="{% url 'articulo_update' articulo.id %}">&#128221;</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'articulo_registro' %}" >&#128190;</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -6,20 +6,21 @@
<div class="col-md-8 offset-md-2 mt-4">
<form method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'articulo_vista' %}"><- volver</a>
<h3 class="col-5">Actualizar articulo</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Actualizar Articulo</h4>
</div>
<div class="card-body">
{% csrf_token %}
{{form.as_p}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">actualizar datos de articulo</button>
</div>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'articulo_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Actualizar articulo</button>
</div>
</div>
</div>
</form>
</div>

@ -7,33 +7,18 @@
<div class="col-md-8 offset-md-2 mt-4">
<form action="/bodega/crearbodega/" method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'bodega_vista' %}"> <- volver</a>
<h3 class="col-5">Registro bodega</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Registrar nueva bodega</h4>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">Crear nueva bodega</button>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'bodega_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Crear nueva bodega</button>
</div>
</div>
</div>
</form>

@ -5,34 +5,19 @@
<div class="row">
<div class="col-md-10 offset-md-1 mt-4">
<form action="/bodega/" method="POST">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<div class="card-header row col-12 justify-content-end mb-2 pr-0 mt-2">
<h3 class="col-md-4">Vista Bodega</h3>
<a class="btn btn-success col-md-3" href="{% url 'bodega_registro' %}">Nueva bodega</a>
<h3 class="text-center">Tabla de Bodega</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">codigo de la bodega</th>
<th scope="col">nombre del supervisor</th>
<th scope="col">estado</th>
<th scope="col">Codigo de la bodega</th>
<th scope="col">Nombre la bodega</th>
<th scope="col">Estado</th>
<th scope="col">Direccion</th>
<th scope="col">Editar</th>
<th scope="col">ACTUALIZAR</th>
</tr>
</thead>
<tbody>
@ -47,14 +32,23 @@
<td> inactivo </td>
{% endif %}
<td> {{bodega.direccion_bodega}} </td>
<td> <a class="btn btn-warning" href="{% url 'bodega_update' bodega.id %}">Editar</a> </td>
<td class="text-center"> <a class="btn btn-secondary" href="{% url 'bodega_update' bodega.id %}">&#128221;</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'bodega_registro' %}" >&#128190;</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -6,35 +6,20 @@
<div class="col-md-8 offset-md-2 mt-4">
<form method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'bodega_vista' %}"><- volver</a>
<h3 class="col-5">Actualizar bodega</h3>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
bodega a sido actualizado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<div class="card-header text-bg-secondary">
<h4 class="text-center">Actualizar Bodega</h4>
</div>
<div class="card-body">
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">actualizar datos de proveedor</button>
</div>
</div>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'bodega_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Actualizar bodega</button>
</div>
</div>
</div>
</form>
</div>

@ -2,179 +2,7 @@
{% block content %}
{% if user.is_authenticated %}
<main class="conteiner col-md-10 offset-md-1 mt-5 g-4">
<div class="row row-cols-1 row-cols-md-2 g-4">
<div class="col">
<div class="card h-100">
<div class="card-body">
<p class="text-center">Precio promedio de cada tipo articulo</p>
<div class="chart-container">
<canvas id="avgPriceChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-body">
<p class="text-center">articulos en bodegas</p>
<div class="chart-container">
<canvas id="barChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-body">
<p class="text-center">Cantidad de tipos de articulos</p>
<div class="chart-container">
<canvas id="graficoLinealMovimientos"></canvas>
</div>
<br>
<div class="text-center">
<p class="text-center">Reportes del inventario</p>
<a href="{% url 'generar_reporte_pdf' %}" class="btn btn-primary">Descargar PDF</a>
<a href="{% url 'generar_reporte_excel' %}" class="btn btn-success">Descargar Excel</a>
<a href="{% url 'generar_reporte_csv' %}" class="btn btn-info">Descargar CSV</a>
</div>
<br>
<p class="text-center">Grafico de productos</p>
<div class="text-center">
<a href="{% url 'generar_grafico_chartjs' %}" class="btn btn-secondary">generar grafico de produccion</a>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-body">
<p class="text-center">Cantidad de tipos de articulos</p>
<div class="chart-container">
<canvas id="pieChart"></canvas>
</div>
</div>
</div>
</div>
</main>
<script>
// Datos dinámicos generados desde Django
const tiposArticulo = {{ tipos_articulo | safe }};
const cantidadesPorTipo = {{ cantidades_por_tipo | safe }};
const bodegas = {{ bodegas | safe }};
const cantidadesPorBodega = {{ cantidades_por_bodega | safe }};
const tiposArticuloProm = {{ tipos_articulo_prom | safe }};
const preciosPromedio = {{ precios_promedio | safe }};
// 1. Gráfico de Pastel: Distribución de artículos por tipo
new Chart(document.getElementById('pieChart').getContext('2d'), {
type: 'pie',
data: {
labels: tiposArticulo,
datasets: [{
data: cantidadesPorTipo,
backgroundColor: ['rgba(255, 99, 132, 0.6)', 'rgba(54, 162, 235, 0.6)', 'rgba(255, 206, 86, 0.6)', 'rgba(75, 192, 192, 0.6)'],
}]
},
options: {
responsive: true,
plugins: {
legend: { position: 'top' },
}
}
});
// 2. Gráfico de Barras: Cantidad de artículos por bodega
new Chart(document.getElementById('barChart').getContext('2d'), {
type: 'bar',
data: {
labels: bodegas,
datasets: [{
label: 'Cantidad de Artículos',
data: cantidadesPorBodega,
backgroundColor: 'rgba(75, 192, 192, 0.6)',
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false },
},
scales: {
x: { title: { display: true, text: 'Bodegas' } },
y: { title: { display: true, text: 'Cantidad' } },
}
}
});
// 3. Gráfico de Línea: Evolución de movimientos de inventario
new Chart(document.getElementById('avgPriceChart').getContext('2d'), {
type: 'bar',
data: {
labels: tiposArticuloProm,
datasets: [{
label: 'Precio Promedio',
data: preciosPromedio,
backgroundColor: 'rgba(255, 159, 64, 0.6)',
}]
},
options: {
responsive: true,
plugins: {
legend: { position: 'top' },
},
scales: {
x: { title: { display: true, text: 'Tipos de Artículos' } },
y: { title: { display: true, text: 'Precio Promedio' } },
}
}
});
const ctx = document.getElementById('graficoLinealMovimientos').getContext('2d');
const graficoLineal = new Chart(ctx, {
type: 'line',
data: {
labels: {{ nombres_tipos|safe }}, // Nombres de los tipos de movimientos
datasets: [{
label: 'Cantidad Total Movida',
data: {{ cantidades_por_tipos|safe }}, // Cantidades totales por tipo de movimiento
borderColor: 'rgba(54, 162, 235, 1)',
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderWidth: 2,
tension: 0.3, // Para suavizar la línea
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: true,
},
tooltip: {
enabled: true,
}
},
scales: {
x: {
title: {
display: true,
text: 'Tipos de Movimiento'
}
},
y: {
beginAtZero: true,
title: {
display: true,
text: 'Cantidad Total'
}
}
}
}
});
</script>
{% else %}
{% endif %}

@ -7,36 +7,22 @@
<div class="col-md-8 offset-md-2 mt-4">
<form action="/inventariomov/crear/" method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'vista_inventario_mov' %}"><- volver</a>
<h3 class="col-5">Registro inventario</h3>
<div class="card-header text-bg-secondary">
<h3 class="text-center">Registrar nuevo movimiento de inventario</h3>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
inventario a sido creado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<br>
{% csrf_token %}
{{form.as_p}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">Crear nuevo inventario</button>
</div>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'vista_inventario_mov' %}">Cancelar</a>
<button class="btn btn-primary ">Crear nuevo movimiento de inventario</button>
</div>
</div>
</div>
</form>
</div>

@ -5,23 +5,19 @@
<div class="row">
<div class="col-md-10 offset-md-1 mt-4">
<form action="/inventario/" method="POST">
<div class="card-header row col-12 justify-content-end mb-2 pr-0 mt-2">
<h3 class="col-md-4">Vista inventario</h3>
<div class="card-header">
<h3 class="text-center">Inventario</h3>
</div>
<a href="{% url 'generar_reporte_pdf' %}" class="btn btn-primary">Descargar PDF</a>
<a href="{% url 'generar_reporte_excel' %}" class="btn btn-success">Descargar Excel</a>
<a href="{% url 'generar_reporte_csv' %}" class="btn btn-info">Descargar CSV</a>
<a href="{% url 'generar_grafico_chartjs' %}" class="btn btn-secondary">grafico</a>
<br>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">articulo</th>
<th scope="col">Articulo</th>
<th scope="col">Descripcion de articulo</th>
<th scope="col">bodega</th>
<th scope="col">cantidad</th>
<th scope="col">precio</th>
<th scope="col">Bodega</th>
<th scope="col">Cantidad</th>
<th scope="col">Precio</th>
</tr>
</thead>
<tbody>
@ -37,9 +33,27 @@
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<div class="btn-group dropup">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
&#128194;
</button>
<ul class="dropdown-menu dropdown-menu-dark">
<!-- Dropdown menu links -->
<li><a class="dropdown-item" href="{% url 'generar_reporte_pdf' %}" >Descargar PDF</a></li>
<li><a class="dropdown-item" href="{% url 'generar_reporte_excel' %}" >Descargar Excel</a></li>
<li><a class="dropdown-item" href="{% url 'generar_reporte_csv' %}">Descargar CSV</a></li>
<li><a class="dropdown-item" href="{% url 'generar_grafico_chartjs' %}">Generar Grafico</a></li>
</ul>
</div>
<br>
</div>
</div>
</main>
{% endblock %}

@ -6,18 +6,17 @@
<div class="col-md-10 offset-md-1 mt-4">
<form action="/inventariomov/" method="POST">
<div class="card-header row col-12 justify-content-end mb-2 pr-0 mt-2">
<h3 class="col-md-4">Vista inventario</h3>
<a class="btn btn-success col-md-3" href="{% url 'registrar_movimiento' %}"> Nuevo movimiento de inventario</a>
<h3 class="text-center">Tabla de movimientos de inventario</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">bodega</th>
<th scope="col">articulo</th>
<th scope="col">cantidad</th>
<th scope="col">precio</th>
<th scope="col">tipo de movimiento</th>
<th scope="col">Bodega</th>
<th scope="col">Articulo</th>
<th scope="col">Cantidad</th>
<th scope="col">Tipo de movimiento</th>
</tr>
</thead>
<tbody>
@ -27,15 +26,22 @@
<td> {{ movimiento_inventario.articulo.nombre_articulo }} {{movimiento_inventario.articulo.medida}} </td>
<td> {{ movimiento_inventario.bodega.nombre_bodega }} </td>
<td> {{ movimiento_inventario.cantidad }} </td>
<td> {{ movimiento_inventario.precio }} </td>
<td> {{ movimiento_inventario.tipo_inventario }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'registrar_movimiento' %}" >&#128190;</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -0,0 +1,30 @@
{% extends "Base.html" %}
{% block content %}
<main class="conteiner">
<div class="row">
<div class="col-md-8 offset-md-2 mt-4">
<form action="/ventas/nueva_venta/" method="POST">
<div class="card">
<div class="card-header text-bg-secondary">
<h4 class="text-center">Registrar nueva venta</h4>
</div>
<div class="card-body">
{% csrf_token %}
{{form.as_p}}
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'lista_ventas' %}">Cancelar</a>
<button class="btn btn-primary ">Nueva venta</button>
</div>
</div>
</div>
</form>
</div>
</div>
</main>
{% endblock %}

@ -8,34 +8,19 @@
<div class="col-md-8 offset-md-2 mt-4">
<form action="/proveedor/crear/" method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'proveedor' %}"><- volver</a>
<h3 class="col-5">Registro Proveedor</h3>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<div class="card-header text-bg-secondary ">
<h4 class="text-center">Registrar Nuevo Proveedor</h4>
</div>
<div class="card-body">
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">Crear nuevo proveedor</button>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'proveedor' %}">Cancelar</a>
<button class="btn btn-primary ">Crear nuevo proveedor</button>
</div>
</div>
</div>
</form>

@ -1,23 +1,23 @@
{% extends "Base.html" %}
{% block content %}
<main class="conteiner">
<main class="conteiner-lg">
<div class="row">
<div class="col-md-10 offset-md-1 mt-4">
<form action="/proveedor/" method="POST">
<div class="card-header justify-content-md-center mb-3">
<h3 class="col-md-4">Proveedores</h3>
<h3 class="text-center">Tabla de proveedores</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Nombre</th>
<th scope="col">Email</th>
<th scope="col">Telefono</th>
<th scope="col">Direccion</th>
<th scope="col">Editar</th>
<th scope="col">ACTUALIZAR</th>
</tr>
</thead>
<tbody>
@ -28,22 +28,26 @@
<td> {{proveedor.email}} </td>
<td> {{proveedor.telefono}} </td>
<td> {{proveedor.direccion}} </td>
<td> <a class="btn btn-warning rounded-pill" href="{% url 'Proveedor_update' proveedor.id %}">Editar</a> </td>
<td class="text-center"> <a class="btn btn-secondary rounded-pill btn-lg" href="{% url 'Proveedor_update' proveedor.id %}">&#128221;</a> </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="sticky-bottom">
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill" href="{% url 'proveedor_registro' %}" >Nuevo proveedor</a>
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'proveedor_registro' %}" >&#128190;</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -6,34 +6,20 @@
<div class="col-md-8 offset-md-2 mt-4">
<form method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'proveedor' %}"><- volver</a>
<h3 class="col-5">Actualizar Proveedor</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Actualizar proveedor</h4>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido actualizado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">actualizar datos de proveedor</button>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'proveedor' %}">Cancelar</a>
<button class="btn btn-primary ">Actualizar proveedor</button>
</div>
</div>
</div>
</form>

@ -7,35 +7,21 @@
<div class="col-md-8 offset-md-2 mt-4">
<form action="/tipo/creartipo_articulo/" method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'tipo_vista' %}"><- volver</a>
<h3 class="col-5">Registro tipo articulo</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Registrar nuevo tipo de articulo</h4>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
el tipo de articulo a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">Crear nuevo tipo de articulo</button>
</div>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'tipo_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Crear nuevo tipo de articulo</button>
</div>
</div>
</div>
</form>
</div>

@ -5,32 +5,17 @@
<div class="row">
<div class="col-md-10 offset-md-1 mt-4">
<form action="/tipo/" method="POST">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
Proveedor a sido guardado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<div class="card-header row col-12 justify-content-end mb-2 pr-0 mt-2">
<h3 class="col-md-4">Tipos de articulos</h3>
<a class="btn btn-success col-md-3" href="{% url 'tipo_registro' %}">Nuevo tipo de articulo</a>
<div class="card-header">
<h3 class="text-center">Tabla de tipos de articulos</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead>
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">tipo de articulo</th>
<th scope="col">Descripcion</th>
<th scope="col">Actualizar</th>
<th scope="col">ACTUALIZAR</th>
</tr>
</thead>
<tbody>
@ -39,13 +24,21 @@
<th scope="row"> {{tipo_articulo.id}} </th>
<td> {{tipo_articulo.tipo_articulo}} </td>
<td> {{tipo_articulo.descripcion}} </td>
<td> <a class="btn btn-warning" href="{% url 'tipo_update' tipo_articulo.id %}">Editar</a> </td> </tr>
<td class="text-center"> <a class="btn btn-secondary rounded-pill" href="{% url 'tipo_update' tipo_articulo.id %}">&#128221;</a> </td> </tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'tipo_registro' %}" >&#128190</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -6,35 +6,21 @@
<div class="col-md-8 offset-md-2 mt-4">
<form method="POST">
<div class="card">
<div class="card-header row col-12 justify-content-start mb-2 pr-0 mt-2">
<a class="btn btn-danger col-3" href="{% url 'tipo_vista' %}"><- volver</a>
<h3 class="col-5">Actualizar tipo de articulo</h3>
<div class="card-header text-bg-secondary">
<h4 class="text-center">Actualizar proveedor</h4>
</div>
<div class="card-body">
{% if error %}
<div class="alert alert-danger" role="alert">
{{error}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button> </div>
{% endif %}
{% if mensaje %}
<div class="alert alert-success" role="alert">
tipo de articulo a sido actualizado con exito
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
{% csrf_token %}
{{form}}
<div class="d-grid gap-2 col-6 mx-auto mt-3">
<button class="btn btn-primary btn-lg ">actualizar datos de tipo articulo</button>
</div>
</div>
<div class="card-footer">
<div class="gap-3 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-danger" href="{% url 'tipo_vista' %}">Cancelar</a>
<button class="btn btn-primary ">Actualizar tipo de articulo</button>
</div>
</div>
</div>
</form>
</div>

@ -0,0 +1,54 @@
{% extends "Base.html" %}
{% block content %}
<main class="conteiner">
<div class="row">
<div class="col-md-10 offset-md-1 mt-4">
<form action="/ventas/" method="POST">
<div class="card-header">
<h3 class="text-center">Tabla de Bodega</h3>
</div>
<div class="table-responsive">
<table class="table mt-3">
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Fecha</th>
<th scope="col">Bodega</th>
<th scope="col">Artículo</th>
<th scope="col">Cantidad</th>
<th scope="col">Precio Unitario</th>
<th scope="col">Total</th>
<th scope="col">Observaciones</th>
</tr>
</thead>
<tbody>
{% for venta in ventas %}
<tr>
<th scope="row"> {{venta.id}} </th>
<td>{{ venta.fecha }}</td>
<td>{{ venta.bodega }}</td>
<td>{{ venta.articulo.nombre_articulo }}</td>
<td>{{ venta.cantidad }}</td>
<td>${{ venta.precio_unitario }}</td>
<td>${{ venta.total }}</td>
<td>{{ venta.observaciones }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
</div>
</div>
<div class="fixed-bottom col-12 mc-3">
<di class="gap-2 d-md-flex justify-content-md-end mb-3">
<a class="btn btn-success rounded-pill btn-lg" href="{% url 'nueva_venta' %}" >&#128190;</a>
<br>
<br>
</div>
</div>
</main>
{% endblock %}

@ -9,52 +9,14 @@ 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
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 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':
@ -88,7 +50,6 @@ def proveedor_registro(request):
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',{
@ -125,12 +86,9 @@ def bodega_registro(request):
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'
})
new_bodega=form.save(commit=False)
new_bodega.save()
return redirect('bodega_vista')
except ValueError:
return render(request, 'bodega_nuevo.html',{
'form': formulario_bodega,
@ -166,12 +124,10 @@ def tipo_registro(request):
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'
})
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,
@ -208,8 +164,7 @@ def articulo_registro(request):
try:
form = formulario_articulo (request.POST)
form.save()
form = formulario_articulo ()
return redirect('articulo_registro')
return redirect('articulo_vista')
except ValueError:
return render(request, 'articulo_nuevo.html',{
@ -264,6 +219,7 @@ def inventario_vista(request):
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.
"""
@ -275,7 +231,6 @@ def registrar_movimiento_y_actualizar_inventario(movimiento_data):
bodega=movimiento_data['bodega'],
tipo_inventario=movimiento_data['tipo_inventario'],
cantidad=movimiento_data['cantidad'],
precio=movimiento_data['precio'],
observaciones=movimiento_data.get('observaciones', '')
)
@ -283,11 +238,11 @@ def registrar_movimiento_y_actualizar_inventario(movimiento_data):
inventario_obj, created = inventario.objects.get_or_create(
articulo=movimiento.articulo,
bodega=movimiento.bodega,
defaults={'cantidad': 0, 'precio': movimiento.precio}
defaults={'cantidad': 0}
)
# Actualizar stock según el tipo de movimiento
if movimiento.tipo_inventario.id == 1: # Asegúrate de que 'nombre' sea un campo válido
# 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:
@ -296,10 +251,6 @@ def registrar_movimiento_y_actualizar_inventario(movimiento_data):
)
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()
@ -309,6 +260,35 @@ def registrar_movimiento_y_actualizar_inventario(movimiento_data):
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.
@ -319,7 +299,7 @@ def registrar_movimiento(request):
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
return redirect('vista_inventario_mov') # Redirigir a una página de éxito
except ValueError as e:
return render(request, 'inventario_nuevo.html', {
'form': form,
@ -335,3 +315,7 @@ 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})

@ -20,7 +20,8 @@ from Inventario import views, viewspdf
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.generar_grafico_chartjs, name='home'),
# path('',views.generar_grafico_chartjs, name='home'),
path('',views.base, name ='home'),
path('logout/',views.signout, name ='logout'),
path('signin/',views.signin, name ='signin'),
path('proveedor/',views.proveedor_lista, name ='proveedor'),
@ -42,6 +43,9 @@ urlpatterns = [
path('reporte/excel/',viewspdf.generar_reporte_excel, name ='generar_reporte_excel'),
path('reporte/csv/',viewspdf.generar_reporte_csv, name ='generar_reporte_csv'),
path('grafico/chartjs/',viewspdf.generar_grafico_chartjs, name ='generar_grafico_chartjs'),
path('ventas/',views.lista_ventas, name ='lista_ventas'),
path('ventas/nueva_venta/',views.nueva_venta, name ='nueva_venta'),

Loading…
Cancel
Save