commit 21978f74206cffbdc64a617a0f902846d49bb33b Author: Francisco_Borja Date: Sun Dec 15 20:41:05 2024 -0600 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eba74f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ \ No newline at end of file diff --git a/Inventario/__init__.py b/Inventario/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Inventario/__pycache__/__init__.cpython-313.pyc b/Inventario/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..45c559e Binary files /dev/null and b/Inventario/__pycache__/__init__.cpython-313.pyc differ diff --git a/Inventario/__pycache__/admin.cpython-313.pyc b/Inventario/__pycache__/admin.cpython-313.pyc new file mode 100644 index 0000000..8b9af74 Binary files /dev/null and b/Inventario/__pycache__/admin.cpython-313.pyc differ diff --git a/Inventario/__pycache__/apps.cpython-313.pyc b/Inventario/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000..99c0fde Binary files /dev/null and b/Inventario/__pycache__/apps.cpython-313.pyc differ diff --git a/Inventario/__pycache__/forms.cpython-313.pyc b/Inventario/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000..b8fe110 Binary files /dev/null and b/Inventario/__pycache__/forms.cpython-313.pyc differ diff --git a/Inventario/__pycache__/models.cpython-313.pyc b/Inventario/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000..69f475c Binary files /dev/null and b/Inventario/__pycache__/models.cpython-313.pyc differ diff --git a/Inventario/__pycache__/views.cpython-313.pyc b/Inventario/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000..7fdd3c4 Binary files /dev/null and b/Inventario/__pycache__/views.cpython-313.pyc differ diff --git a/Inventario/__pycache__/viewspdf.cpython-313.pyc b/Inventario/__pycache__/viewspdf.cpython-313.pyc new file mode 100644 index 0000000..cbef389 Binary files /dev/null and b/Inventario/__pycache__/viewspdf.cpython-313.pyc differ diff --git a/Inventario/admin.py b/Inventario/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/Inventario/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/Inventario/apps.py b/Inventario/apps.py new file mode 100644 index 0000000..96b6bd7 --- /dev/null +++ b/Inventario/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InventarioConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Inventario' diff --git a/Inventario/forms.py b/Inventario/forms.py new file mode 100644 index 0000000..2d57d19 --- /dev/null +++ b/Inventario/forms.py @@ -0,0 +1,99 @@ +from django import forms +from .models import proveedor, bodega, tipo_articulo, articulo,inventario,tipo_inv_movimiento + +class formulario_proveedor(forms.ModelForm): + class Meta: + model = proveedor + fields = '__all__' + widgets={ + 'nombre_proveedor': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'Escribe el nombre del proveedor'}), + 'email': forms.EmailInput(attrs={'class':'form-control','placeholder':'email del proveedor'}), + 'direccion': forms.Textarea(attrs={'class':'form-control','placeholder':'direccion del proveedor','rows':'5'}), + 'telefono': forms.TextInput(attrs={'type':'tel','class':'form-control','placeholder':'0000-0000','maxlength':'9' ,'oninput':'formatearInput(this)'}), + } + +class formulario_bodega(forms.ModelForm): + class Meta: + model = bodega + fields = '__all__' + widgets={ + 'nombre_bodega': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'Escribe el nombre de la bodega'}), + 'estado': forms.CheckboxInput(attrs={'class':'form-check-input'}), + 'direccion_bodega': forms.Textarea(attrs={'class':'form-control','placeholder':'direccion de la bodega','rows':'5'}), + 'codigo_bodega': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'Escribe el codigo de la bodega','oninput':'permitirSoloNumeros(this)'}), + } + +class formulario_tipo(forms.ModelForm): + class Meta: + model = tipo_articulo + fields = '__all__' + widgets={ + 'tipo_articulo': forms.TextInput(attrs={'class': 'form-control' , 'placeholder': 'escriba el tipo de articulo'}), + 'descripcion': forms.Textarea(attrs={'class':'form-control','placeholder':'escriba una descripcion de este tipo de articulo','rows':'5'}), + } + +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") + 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") + class Meta: + model = articulo + fields = '__all__' + widgets={ + '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): + + 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") + class Meta: + model = inventario + 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): + tipo_inventario=forms.ModelChoiceField(queryset=tipo_inv_movimiento.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="tipo de inventario") + 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") + articulo=forms.ModelChoiceField(queryset=articulo.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="articulo") + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Personaliza cómo se muestran las opciones en el dropdown + self.fields['articulo'].label_from_instance = lambda obj: f"{obj.nombre_articulo} ({obj.medida})" if obj.medida else obj.nombre_articulo + self.fields['bodega'].label_from_instance = lambda obj: f"{obj.nombre_bodega} ({obj.codigo_bodega})" if obj.codigo_bodega else obj.nombre_bodega + + + class Meta: + model = inventario + 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'}), + } diff --git a/Inventario/migrations/0001_initial.py b/Inventario/migrations/0001_initial.py new file mode 100644 index 0000000..1790f77 --- /dev/null +++ b/Inventario/migrations/0001_initial.py @@ -0,0 +1,76 @@ +# Generated by Django 5.1.4 on 2024-12-11 06:38 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='bodega', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('codigo_bodega', models.IntegerField()), + ('nombre_bodega', models.CharField(max_length=40)), + ('estado', models.BooleanField(default=True)), + ], + ), + migrations.CreateModel( + name='proveedor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre_proveedor', models.CharField(max_length=100)), + ('email', models.EmailField(blank=True, max_length=254, null=True)), + ('telefono', models.CharField(blank=True, max_length=20, null=True)), + ('direccion', models.TextField(blank=True, null=True)), + ('estado', models.BooleanField(default=True)), + ], + ), + migrations.CreateModel( + name='tipo_articulo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('tipo_articulo', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='tipo_inv_movimiento', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('tipo_movimiento', models.CharField(max_length=100)), + ], + ), + migrations.CreateModel( + name='articulo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre_articulo', models.CharField(max_length=100)), + ('precio_articulo', models.DecimalField(decimal_places=2, max_digits=10)), + ('stock', models.IntegerField()), + ('creado', models.DateTimeField(auto_now_add=True)), + ('actualizado', models.DateTimeField(auto_now=True)), + ('activo', models.BooleanField(default=True)), + ('bodega', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bodega', to='Inventario.bodega')), + ('proveedor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='productos', to='Inventario.proveedor')), + ], + ), + migrations.CreateModel( + name='movimiento_inventario', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cantidad', models.IntegerField()), + ('descripcion', models.TextField(blank=True)), + ('total_costo', models.DecimalField(decimal_places=2, max_digits=10)), + ('numero_mov', models.IntegerField()), + ('fecha', models.DateTimeField(auto_now_add=True)), + ('articulo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='articulos', to='Inventario.articulo')), + ('tipo_movimiento', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mov_inv', to='Inventario.tipo_inv_movimiento')), + ], + ), + ] diff --git a/Inventario/migrations/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.py b/Inventario/migrations/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.py new file mode 100644 index 0000000..09b6323 --- /dev/null +++ b/Inventario/migrations/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.py @@ -0,0 +1,138 @@ +# Generated by Django 5.1.4 on 2024-12-13 02:59 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Inventario', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='movimiento_inventario', + old_name='descripcion', + new_name='observaciones', + ), + migrations.RenameField( + model_name='movimiento_inventario', + old_name='total_costo', + new_name='precio', + ), + migrations.RemoveField( + model_name='articulo', + name='activo', + ), + migrations.RemoveField( + model_name='articulo', + name='actualizado', + ), + migrations.RemoveField( + model_name='articulo', + name='bodega', + ), + migrations.RemoveField( + model_name='articulo', + name='creado', + ), + migrations.RemoveField( + model_name='articulo', + name='precio_articulo', + ), + migrations.RemoveField( + model_name='articulo', + name='stock', + ), + migrations.RemoveField( + model_name='movimiento_inventario', + name='numero_mov', + ), + migrations.RemoveField( + model_name='movimiento_inventario', + name='tipo_movimiento', + ), + migrations.RemoveField( + model_name='proveedor', + name='estado', + ), + migrations.AddField( + model_name='articulo', + name='codigo_articulo', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='articulo', + name='descripcion', + field=models.TextField(blank=True), + ), + migrations.AddField( + model_name='articulo', + name='tipo_articulo', + field=models.ForeignKey(default=40, on_delete=django.db.models.deletion.CASCADE, to='Inventario.tipo_articulo'), + preserve_default=False, + ), + migrations.AddField( + model_name='bodega', + name='direccion_bodega', + field=models.TextField(blank=True), + ), + migrations.AddField( + model_name='movimiento_inventario', + name='bodega', + field=models.ForeignKey(default=60, on_delete=django.db.models.deletion.CASCADE, to='Inventario.bodega'), + preserve_default=False, + ), + migrations.AddField( + model_name='movimiento_inventario', + name='tipo_inventario', + field=models.ForeignKey(default=100, on_delete=django.db.models.deletion.CASCADE, to='Inventario.tipo_inv_movimiento'), + preserve_default=False, + ), + migrations.AddField( + model_name='tipo_articulo', + name='descripcion', + field=models.TextField(blank=True), + ), + migrations.AlterField( + model_name='articulo', + name='proveedor', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Inventario.proveedor'), + ), + migrations.AlterField( + model_name='bodega', + name='codigo_bodega', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='movimiento_inventario', + name='articulo', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Inventario.articulo'), + ), + migrations.AlterField( + model_name='movimiento_inventario', + name='cantidad', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='movimiento_inventario', + name='fecha', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='tipo_articulo', + name='tipo_articulo', + field=models.CharField(max_length=40), + ), + migrations.CreateModel( + name='inventario', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cantidad', models.IntegerField(null=True)), + ('precio', models.DecimalField(decimal_places=2, max_digits=10)), + ('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')), + ], + ), + ] diff --git a/Inventario/migrations/0003_remove_articulo_codigo_articulo_articulo_medida.py b/Inventario/migrations/0003_remove_articulo_codigo_articulo_articulo_medida.py new file mode 100644 index 0000000..21ed427 --- /dev/null +++ b/Inventario/migrations/0003_remove_articulo_codigo_articulo_articulo_medida.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.4 on 2024-12-15 18:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Inventario', '0002_rename_descripcion_movimiento_inventario_observaciones_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='articulo', + name='codigo_articulo', + ), + migrations.AddField( + model_name='articulo', + name='medida', + field=models.CharField(blank=True, max_length=100, null=True), + ), + ] diff --git a/Inventario/migrations/__init__.py b/Inventario/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Inventario/migrations/__pycache__/0001_initial.cpython-313.pyc b/Inventario/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000..32fc542 Binary files /dev/null and b/Inventario/migrations/__pycache__/0001_initial.cpython-313.pyc differ diff --git a/Inventario/migrations/__pycache__/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.cpython-313.pyc b/Inventario/migrations/__pycache__/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.cpython-313.pyc new file mode 100644 index 0000000..b3af699 Binary files /dev/null and b/Inventario/migrations/__pycache__/0002_rename_descripcion_movimiento_inventario_observaciones_and_more.cpython-313.pyc differ diff --git a/Inventario/migrations/__pycache__/0003_remove_articulo_codigo_articulo_articulo_medida.cpython-313.pyc b/Inventario/migrations/__pycache__/0003_remove_articulo_codigo_articulo_articulo_medida.cpython-313.pyc new file mode 100644 index 0000000..ce8a412 Binary files /dev/null and b/Inventario/migrations/__pycache__/0003_remove_articulo_codigo_articulo_articulo_medida.cpython-313.pyc differ diff --git a/Inventario/migrations/__pycache__/__init__.cpython-313.pyc b/Inventario/migrations/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..f740e6c Binary files /dev/null and b/Inventario/migrations/__pycache__/__init__.cpython-313.pyc differ diff --git a/Inventario/models.py b/Inventario/models.py new file mode 100644 index 0000000..c0078ce --- /dev/null +++ b/Inventario/models.py @@ -0,0 +1,58 @@ +from django.db import models +from django.contrib.auth.models import User + + +# Create your models here. +class tipo_articulo(models.Model): + tipo_articulo= models.CharField(max_length=40) + descripcion=models.TextField(blank=True) + def __str__(self): + return self.tipo_articulo + +class proveedor(models.Model): + nombre_proveedor=models.CharField(max_length=100) + email = models.EmailField(null=True, blank=True) + telefono = models.CharField(max_length=20, null=True, blank=True) + direccion = models.TextField(null=True, blank=True) + def __str__(self): + return self.nombre_proveedor + +class tipo_inv_movimiento(models.Model): + tipo_movimiento=models.CharField(max_length=100) + def __str__(self): + return self.tipo_movimiento + +class bodega(models.Model): + codigo_bodega=models.IntegerField(null=True) + nombre_bodega= models.CharField(max_length=40) + direccion_bodega=models.TextField(blank=True) + estado= models.BooleanField(default=True) + def __str__(self): + return self.nombre_bodega + +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) + proveedor = models.ForeignKey(proveedor, on_delete=models.CASCADE) + tipo_articulo=models.ForeignKey(tipo_articulo, on_delete=models.CASCADE) + def __str__(self): + return self.nombre_articulo + + +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 movimiento_inventario(models.Model): + fecha=models.DateTimeField(null=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) + diff --git a/Inventario/templates/Base.html b/Inventario/templates/Base.html new file mode 100644 index 0000000..1cd87d4 --- /dev/null +++ b/Inventario/templates/Base.html @@ -0,0 +1,105 @@ + + + + + + Tienda la esquina + + + + + + + +{% block content %} + +{% endblock %} + + + + + + + \ No newline at end of file diff --git a/Inventario/templates/articulo_nuevo.html b/Inventario/templates/articulo_nuevo.html new file mode 100644 index 0000000..f8e8eb1 --- /dev/null +++ b/Inventario/templates/articulo_nuevo.html @@ -0,0 +1,51 @@ +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+
+
+ <- volver +

Registro articulo

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form.as_p}} + +
+ +
+ +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/articulo_registro.html b/Inventario/templates/articulo_registro.html new file mode 100644 index 0000000..907fff9 --- /dev/null +++ b/Inventario/templates/articulo_registro.html @@ -0,0 +1,44 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+

Vista articulo

+ Nuevo articulo +
+ + + + + + + + + + + + + + + {% for articulo in persona %} + + + + + + + + + + {% endfor %} + +
#nombre del articulomedidadescripciontipo_articuloproveedorsactualizar
{{ articulo.id }} {{ articulo.nombre_articulo }} {{ articulo.medida }} {{ articulo.descripcion }} {{ articulo.tipo_articulo.tipo_articulo }} {{ articulo.proveedor.nombre_proveedor }} Editar
+
+
+
+
+ +{% endblock %} diff --git a/Inventario/templates/articulo_update.html b/Inventario/templates/articulo_update.html new file mode 100644 index 0000000..6b7b0ea --- /dev/null +++ b/Inventario/templates/articulo_update.html @@ -0,0 +1,29 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+
+ <- volver +

Actualizar articulo

+ +
+
+ {% csrf_token %} + {{form.as_p}} + +
+ +
+ +
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/bodega_nuevo.html b/Inventario/templates/bodega_nuevo.html new file mode 100644 index 0000000..a0bbba0 --- /dev/null +++ b/Inventario/templates/bodega_nuevo.html @@ -0,0 +1,51 @@ +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+
+
+ <- volver +

Registro bodega

+
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+ + + + +{% endblock %} diff --git a/Inventario/templates/bodega_registro.html b/Inventario/templates/bodega_registro.html new file mode 100644 index 0000000..1bbd654 --- /dev/null +++ b/Inventario/templates/bodega_registro.html @@ -0,0 +1,60 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} +
+

Vista Bodega

+ Nueva bodega +
+ + + + + + + + + + + + + {% for bodega in persona %} + + + + + {% if bodega.estado %} + + {% else %} + + {% endif %} + + + + {% endfor %} + +
#codigo de la bodeganombre del supervisorestadoDireccionEditar
{{bodega.id}} {{bodega.codigo_bodega}} {{bodega.nombre_bodega}} activo inactivo {{bodega.direccion_bodega}} Editar
+
+
+
+
+ +{% endblock %} diff --git a/Inventario/templates/bodega_update.html b/Inventario/templates/bodega_update.html new file mode 100644 index 0000000..b2f6806 --- /dev/null +++ b/Inventario/templates/bodega_update.html @@ -0,0 +1,43 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+
+ <- volver +

Actualizar bodega

+
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/grafico_chartjs.html b/Inventario/templates/grafico_chartjs.html new file mode 100644 index 0000000..0016d87 --- /dev/null +++ b/Inventario/templates/grafico_chartjs.html @@ -0,0 +1,36 @@ + + + + Gráfico Interactivo + + + +

Gráfico de cantidad de productos

+ + + volver + + + \ No newline at end of file diff --git a/Inventario/templates/index.html b/Inventario/templates/index.html new file mode 100644 index 0000000..a95d814 --- /dev/null +++ b/Inventario/templates/index.html @@ -0,0 +1,181 @@ +{% extends "Base.html" %} + +{% block content %} +{% if user.is_authenticated %} +
+
+
+
+
+

Precio promedio de cada tipo articulo

+
+ +
+
+
+
+
+
+
+

articulos en bodegas

+
+ +
+
+
+
+
+
+
+

Cantidad de tipos de articulos

+
+ +
+
+
+

Reportes del inventario

+ Descargar PDF + Descargar Excel + Descargar CSV +
+
+

Grafico de productos

+ +
+
+
+
+
+
+

Cantidad de tipos de articulos

+
+ +
+
+
+
+ + +
+ +{% else %} +{% endif %} + +{% endblock %} diff --git a/Inventario/templates/inventario_nuevo.html b/Inventario/templates/inventario_nuevo.html new file mode 100644 index 0000000..009d2a6 --- /dev/null +++ b/Inventario/templates/inventario_nuevo.html @@ -0,0 +1,52 @@ +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+
+
+ <- volver +

Registro inventario

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form.as_p}} + +
+ +
+ +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/inventario_registro.html b/Inventario/templates/inventario_registro.html new file mode 100644 index 0000000..542891a --- /dev/null +++ b/Inventario/templates/inventario_registro.html @@ -0,0 +1,45 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+

Vista inventario

+
+ Descargar PDF + Descargar Excel + Descargar CSV + grafico +
+ + + + + + + + + + + + + {% for inventario in persona %} + + + + + + + + + {% endfor %} + +
#articuloDescripcion de articulobodegacantidadprecio
{{ inventario.id }} {{ inventario.articulo.nombre_articulo }} {{inventario.articulo.medida}} {{ inventario.articulo.descripcion }} {{ inventario.bodega.nombre_bodega }} {{ inventario.cantidad }} {{ inventario.precio }}
+
+
+
+
+ +{% endblock %} diff --git a/Inventario/templates/mov_inventario_registro.html b/Inventario/templates/mov_inventario_registro.html new file mode 100644 index 0000000..bfdf02f --- /dev/null +++ b/Inventario/templates/mov_inventario_registro.html @@ -0,0 +1,41 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+

Vista inventario

+ Nuevo movimiento de inventario +
+ + + + + + + + + + + + + {% for movimiento_inventario in persona %} + + + + + + + + + {% endfor %} + +
#bodegaarticulocantidadpreciotipo de movimiento
{{ movimiento_inventario.id }} {{ movimiento_inventario.articulo.nombre_articulo }} {{movimiento_inventario.articulo.medida}} {{ movimiento_inventario.bodega.nombre_bodega }} {{ movimiento_inventario.cantidad }} {{ movimiento_inventario.precio }} {{ movimiento_inventario.tipo_inventario }}
+
+
+
+
+ +{% endblock %} diff --git a/Inventario/templates/pdf.html b/Inventario/templates/pdf.html new file mode 100644 index 0000000..02d5c73 --- /dev/null +++ b/Inventario/templates/pdf.html @@ -0,0 +1,36 @@ + + + + + + +

Reporte de Inventario

+ + + + + + + + + + + + {% for item in inventarios %} + + + + + + + + {% endfor %} + +
IDBodegaArtículoCantidadPrecio
{{ item.id }}{{ item.bodega.nombre_bodega }}{{ item.articulo.nombre_articulo }}{{ item.cantidad }}{{ item.precio }}
+ + \ No newline at end of file diff --git a/Inventario/templates/proveedor_nuevo.html b/Inventario/templates/proveedor_nuevo.html new file mode 100644 index 0000000..ae93b0f --- /dev/null +++ b/Inventario/templates/proveedor_nuevo.html @@ -0,0 +1,56 @@ + +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+
+
+ <- volver +

Registro Proveedor

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/proveedor_registro.html b/Inventario/templates/proveedor_registro.html new file mode 100644 index 0000000..19d9323 --- /dev/null +++ b/Inventario/templates/proveedor_registro.html @@ -0,0 +1,56 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} +
+

Proveedores

+ Nuevo proveedor +
+ + + + + + + + + + + + + {% for proveedor in persona %} + + + + + + + + + {% endfor %} + +
#NombreEmailTelefonoDireccionEditar
{{proveedor.id}} {{proveedor.nombre_proveedor}} {{proveedor.email}} {{proveedor.telefono}} {{proveedor.direccion}} Editar
+
+
+
+
+ +{% endblock %} diff --git a/Inventario/templates/proveedor_update.html b/Inventario/templates/proveedor_update.html new file mode 100644 index 0000000..d0fd843 --- /dev/null +++ b/Inventario/templates/proveedor_update.html @@ -0,0 +1,43 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+
+ <- volver +

Actualizar Proveedor

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/signin.html b/Inventario/templates/signin.html new file mode 100644 index 0000000..8ac8644 --- /dev/null +++ b/Inventario/templates/signin.html @@ -0,0 +1,28 @@ +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+

Login

+ {% csrf_token %} +
+ + +
+
+ + +
+ +
+
+
+
+ + +{% endblock %} diff --git a/Inventario/templates/tipo_articulo_nuevo.html b/Inventario/templates/tipo_articulo_nuevo.html new file mode 100644 index 0000000..4a90802 --- /dev/null +++ b/Inventario/templates/tipo_articulo_nuevo.html @@ -0,0 +1,44 @@ +{% extends "Base.html" %} + +{% block content %} + +
+
+
+
+
+
+ <- volver +

Registro tipo articulo

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/tipo_articulo_registro.html b/Inventario/templates/tipo_articulo_registro.html new file mode 100644 index 0000000..bf03a29 --- /dev/null +++ b/Inventario/templates/tipo_articulo_registro.html @@ -0,0 +1,51 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} +
+

Tipos de articulos

+ Nuevo tipo de articulo +
+ + + + + + + + + + + {% for tipo_articulo in persona %} + + + + + + {% endfor %} + +
#tipo de articuloDescripcionActualizar
{{tipo_articulo.id}} {{tipo_articulo.tipo_articulo}} {{tipo_articulo.descripcion}} Editar
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/Inventario/templates/tipo_articulo_update.html b/Inventario/templates/tipo_articulo_update.html new file mode 100644 index 0000000..80d194f --- /dev/null +++ b/Inventario/templates/tipo_articulo_update.html @@ -0,0 +1,43 @@ +{% extends "Base.html" %} + +{% block content %} +
+
+
+
+
+
+ <- volver +

Actualizar tipo de articulo

+ +
+
+ {% if error %} + + {% endif %} + {% if mensaje %} + + {% endif %} + {% csrf_token %} + {{form}} + +
+ +
+ +
+
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/Inventario/tests.py b/Inventario/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Inventario/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/Inventario/views.py b/Inventario/views.py new file mode 100644 index 0000000..b943dfa --- /dev/null +++ b/Inventario/views.py @@ -0,0 +1,338 @@ +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}) + diff --git a/Inventario/viewspdf.py b/Inventario/viewspdf.py new file mode 100644 index 0000000..77b98ac --- /dev/null +++ b/Inventario/viewspdf.py @@ -0,0 +1,83 @@ +from django.contrib.auth.decorators import login_required +from django.http import HttpResponse +import openpyxl +import csv +from django.template.loader import get_template +from xhtml2pdf import pisa +from django.shortcuts import render +from .models import inventario + +@login_required +def generar_reporte_pdf(request): + # Obtener datos del inventario + inventarios = inventario.objects.all() + + # Cargar la plantilla + template = get_template('pdf.html') + context = {'inventarios': inventarios} + + # Renderizar la plantilla a HTML + html = template.render(context) + + # Crear un objeto de respuesta PDF + response = HttpResponse(content_type='application/pdf') + response['Content-Disposition'] = 'inline; filename="reporte.pdf"' + + # Convertir HTML a PDF + pisa_status = pisa.CreatePDF(html, dest=response) + + if pisa_status.err: + return HttpResponse(f'Error al generar PDF: {pisa_status.err}', status=500) + + return response + +@login_required +def generar_reporte_excel(request): + # Crear un nuevo libro de Excel + wb = openpyxl.Workbook() + ws = wb.active + ws.title = 'Reporte de Inventario' + + # Encabezados + headers = ['ID', 'Bodega', 'Artículo', 'Cantidad', 'Precio'] + ws.append(headers) + + # Datos del inventario + for item in inventario.objects.all(): + ws.append([item.id, item.bodega.nombre_bodega, item.articulo.nombre_articulo, item.cantidad, item.precio]) + + # Configurar la respuesta HTTP + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename="reporte_inventario.xlsx"' + + # Guardar el archivo en la respuesta + wb.save(response) + return response + +@login_required +def generar_reporte_csv(request): + # Configurar la respuesta HTTP + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="reporte_inventario.csv"' + + writer = csv.writer(response) + + # Encabezados + writer.writerow(['ID', 'Bodega', 'Artículo', 'Cantidad', 'Precio']) + + # Datos del inventario + for item in inventario.objects.all(): + writer.writerow([item.id, item.bodega.nombre_bodega, item.articulo.nombre_articulo, item.cantidad, item.precio]) + + return response + +@login_required +def generar_grafico_chartjs(request): + inventarios = inventario.objects.all() + productos = [item.articulo.nombre_articulo for item in inventarios] + cantidades = [item.cantidad for item in inventarios] + + return render(request, 'grafico_chartjs.html', { + 'productos': productos, + 'cantidades': cantidades, + }) \ No newline at end of file diff --git a/TiendAlfa/__init__.py b/TiendAlfa/__init__.py new file mode 100644 index 0000000..063cd2c --- /dev/null +++ b/TiendAlfa/__init__.py @@ -0,0 +1,2 @@ +import pymysql +pymysql.install_as_MySQLdb() diff --git a/TiendAlfa/__pycache__/__init__.cpython-313.pyc b/TiendAlfa/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..1560d07 Binary files /dev/null and b/TiendAlfa/__pycache__/__init__.cpython-313.pyc differ diff --git a/TiendAlfa/__pycache__/settings.cpython-313.pyc b/TiendAlfa/__pycache__/settings.cpython-313.pyc new file mode 100644 index 0000000..0b3f294 Binary files /dev/null and b/TiendAlfa/__pycache__/settings.cpython-313.pyc differ diff --git a/TiendAlfa/__pycache__/urls.cpython-313.pyc b/TiendAlfa/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000..fda880c Binary files /dev/null and b/TiendAlfa/__pycache__/urls.cpython-313.pyc differ diff --git a/TiendAlfa/__pycache__/wsgi.cpython-313.pyc b/TiendAlfa/__pycache__/wsgi.cpython-313.pyc new file mode 100644 index 0000000..e39e223 Binary files /dev/null and b/TiendAlfa/__pycache__/wsgi.cpython-313.pyc differ diff --git a/TiendAlfa/asgi.py b/TiendAlfa/asgi.py new file mode 100644 index 0000000..208551f --- /dev/null +++ b/TiendAlfa/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for TiendAlfa project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TiendAlfa.settings') + +application = get_asgi_application() diff --git a/TiendAlfa/settings.py b/TiendAlfa/settings.py new file mode 100644 index 0000000..ecf49b9 --- /dev/null +++ b/TiendAlfa/settings.py @@ -0,0 +1,132 @@ +""" +Django settings for TiendAlfa project. + +Generated by 'django-admin startproject' using Django 5.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-f)f0@t_(a&ht0mo$&#nftao+_=s&^31u9))d=685^vs8&np=5k' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['store.stevz.dev','127.0.0.1'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'Inventario', + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'TiendAlfa.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'TiendAlfa.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', # Motor de MySQL + 'NAME': 'ttienda', # Nombre de la base de datos + 'USER': 'ttienda', # Usuario de MySQL + 'PASSWORD': 'Tienda$2024', # Contraseña de MySQL + 'HOST': '10.138.214.232', # Dirección del servidor (por defecto localhost) + 'PORT': '3306', # Puerto de MySQL (por defecto 3306) + } +} + + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = 'static/' + +LOGIN_URL= '/signin/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/TiendAlfa/urls.py b/TiendAlfa/urls.py new file mode 100644 index 0000000..cd6fca4 --- /dev/null +++ b/TiendAlfa/urls.py @@ -0,0 +1,54 @@ +""" +URL configuration for TiendAlfa project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from Inventario import views, viewspdf + +urlpatterns = [ + path('admin/', admin.site.urls), + path('',views.generar_grafico_chartjs, name='home'), + path('logout/',views.signout, name ='logout'), + path('signin/',views.signin, name ='signin'), + path('proveedor/',views.proveedor_lista, name ='proveedor'), + path('proveedor/crear/',views.proveedor_registro, name ='proveedor_registro'), + path('proveedor//',views.Proveedor_update, name ='Proveedor_update'), + path('bodega/',views.bodega_vista, name ='bodega_vista'), + path('bodega/crearbodega/',views.bodega_registro, name ='bodega_registro'), + path('bodega//',views.bodega_update, name ='bodega_update'), + path('tipo/',views.tipo_vista, name ='tipo_vista'), + path('tipo/creartipo_articulo/',views.tipo_registro, name ='tipo_registro'), + path('tipo//',views.tipo_update, name ='tipo_update'), + path('articulo/',views.articulo_vista, name ='articulo_vista'), + path('articulo/crear/',views.articulo_registro, name ='articulo_registro'), + path('articulo//',views.articulo_update, name ='articulo_update'), + path('inventario/',views.inventario_vista, name ='inventario_vista'), + path('inventariomov/crear/',views.registrar_movimiento, name ='registrar_movimiento'), + path('inventariomov/',views.vista_inventario_mov, name ='vista_inventario_mov'), + path('reporte/pdf/',viewspdf.generar_reporte_pdf, name ='generar_reporte_pdf'), + 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'), + + + + + + + + + +] diff --git a/TiendAlfa/wsgi.py b/TiendAlfa/wsgi.py new file mode 100644 index 0000000..b2070e8 --- /dev/null +++ b/TiendAlfa/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for TiendAlfa project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TiendAlfa.settings') + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..7740509 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TiendAlfa.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main()