From 317b2a04277a61b5060f52b97d44544b1bd233dd Mon Sep 17 00:00:00 2001 From: Francisco_Borja Date: Tue, 17 Dec 2024 19:40:59 -0600 Subject: [PATCH] =?UTF-8?q?dise=C3=B1os=20v2,=20precios=20en=20articulos?= =?UTF-8?q?=20y=20=20sector=20de=20ventas/=20reportes=20borrados=20para=20?= =?UTF-8?q?mejorar=20e=20actualizar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inventario/__pycache__/forms.cpython-313.pyc | Bin 8538 -> 9945 bytes Inventario/__pycache__/models.cpython-313.pyc | Bin 4781 -> 7495 bytes Inventario/__pycache__/views.cpython-313.pyc | Bin 15392 -> 14559 bytes Inventario/forms.py | 43 ++++- .../0004_remove_inventario_precio_and_more.py | 50 +++++ ...inventario_precio_and_more.cpython-313.pyc | Bin 0 -> 2486 bytes Inventario/models.py | 55 +++++- Inventario/templates/Base.html | 18 +- Inventario/templates/articulo_nuevo.html | 29 +-- Inventario/templates/articulo_registro.html | 32 +++- Inventario/templates/articulo_update.html | 15 +- Inventario/templates/bodega_nuevo.html | 29 +-- Inventario/templates/bodega_registro.html | 40 ++-- Inventario/templates/bodega_update.html | 37 ++-- Inventario/templates/index.html | 172 ------------------ Inventario/templates/inventario_nuevo.html | 32 +--- Inventario/templates/inventario_registro.html | 38 ++-- .../templates/mov_inventario_registro.html | 24 ++- Inventario/templates/nueva_venta.html | 30 +++ Inventario/templates/proveedor_nuevo.html | 33 +--- Inventario/templates/proveedor_registro.html | 18 +- Inventario/templates/proveedor_update.html | 30 +-- Inventario/templates/tipo_articulo_nuevo.html | 30 +-- .../templates/tipo_articulo_registro.html | 35 ++-- .../templates/tipo_articulo_update.html | 30 +-- Inventario/templates/ventas.html | 54 ++++++ Inventario/views.py | 114 +++++------- TiendAlfa/__pycache__/urls.cpython-313.pyc | Bin 3099 -> 3275 bytes TiendAlfa/urls.py | 6 +- 29 files changed, 473 insertions(+), 521 deletions(-) create mode 100644 Inventario/migrations/0004_remove_inventario_precio_and_more.py create mode 100644 Inventario/migrations/__pycache__/0004_remove_inventario_precio_and_more.cpython-313.pyc create mode 100644 Inventario/templates/nueva_venta.html create mode 100644 Inventario/templates/ventas.html diff --git a/Inventario/__pycache__/forms.cpython-313.pyc b/Inventario/__pycache__/forms.cpython-313.pyc index b8fe11019716ced405d695bbe8159abe465c0925..6fd3fffbea490b0fc45502f483fab3d2601d9693 100644 GIT binary patch delta 3442 zcmbVOZ){uD6@S-$e)fCM&(Ht=#EEU%bd4!X(y~(eFD-5Q2iBx5uPLQec+T@9c(P;n zKBqt`WXh&0fCPkFsSOee0wGZ}P18C}Y(j`nh!5M;=8pFOI~)B;tzSJghzLlxqx!ZZ1uAWBpxH|bO#o9m@&rCF^qwU4UR zX0@NG{Zt)jQnv+0g4xg_c%4O->zN8Jn~MlWZc;`AZp(Gr7_H@R{1Gi6Awu;yO5Szu zUJ-9OzeJnJr~E18Cn47>hqi*ng8-W-3|<%Tk6^GFpbH=izzljp0xQfWZ39VRKyJAb z0#ho#6$X$H1Z{|D?oK%jVhkWcUUqj22@u=J@7<5cwsSDf5QnF4D{~;Lv~)lKv-<(I z05}02Am=@y&TbHU09yIS9N$Gg^t`xtO{DlIFlS9TJ3t4Zg0LNcP22I7aFl!`{$VAu zqI92NM@HV19$E?NPg49zI|y&fAl$It+8{u84>24ed*z|~?r?c}ktY!z;{`te#T zo6!-<(dc#u-5B;(wHWq~#Ip$!RnDUbnNT)HfdS+GQ^jf}Q!p}lTr28hr3(3-V$?11 z1g=~#j6wyE`%hp)FESgwQm*3sB3#c!SQ&>Xd>cGu>bN*;WX4A6LVB^BFJVZ;bsi7V zA4@9dpU)MFBgL9&`IZfG)lyzJOnizOjH|0VT!4F`leF)1`C&rw|YIZfgccyob~S-w!HoJ zVH_?RrGh07j+KWE{OD+PtY#@ycBVP|KrQd`kVU`##r`P-0kDyNO&*a?{YQj7-?*Kj zJ|YK>*Ow$N6rT%r&IUW@qh0gKj`?(EKGr@L>za*qeVn>^rZm%2o{5cqBl4jtdTC(E z%LQX|fsM0)jq}mXceM{v`(w8yk4tKB6znqqS9JPa{*b2)L=nvm(ge-j?bJLwQ7^)xCSqws z%F5)|p;Y}C%mQjy9z8!=D;Dwvn~ITx%R^vv6;}#ldaYvOJz&2VfbDM+MgBqBz(53O zMUpy(lY=f0Ic@1jayaNGME4ypkMPn3YWPB@@nL&>VgDPuoGCm(Hp&m(i)go09vMu z^v2`zN%*@8aQcQ8--qImcsxwuIEv&TC(u@MpzZ3Gi&UR= z;77o|58y=#E7mZs1H43`K=@=X#SRwY%kq}X9IG1G^5k;G(PAx^!&}IudGU-d8E0jt*NY(2hueWD-N+LIT!;$RZHCgj&3XEw%^>sV3 ztf|;L;?D-GHdrXuJz&)Gi|m9Mz4$`DX3(y=zoWgLqWj_1{>Yd#2D&@!vgFFJY2XWa zS}sSi-BlqDCw&qa`m?mcg8AzJHU(Q}z6Av>v41!9gcT3`04#71?ddgY2ceixk)5ed z@_9H--cLmiyZII@Y*EBumsJu%&Bsk7B>zdJcR>nP%ax_%a(XFmnz~Uc<#JhsCt!Er z#eU3E_8iy)Xyl3Xzf`wNy3J9r$@m=WiG}~s6YFccox)yZVcP8?ceCWwB*KDS z$m;7BGRt?zHJf#C4YItwA9DmYwUj1G(SA7v+p*pAAl>2EdWEgt1!nBMD1)@7vfTrV zuF`4Xnh8^(utg?ZR-hjWTk_h_^wV!Y{c+#TGov>zyfCwEe5T{#_p2Pc+cw$#E$i(n z!&uBs3tdgFO zX71YWe6-&ky)AveT*BIe*&r!o9;{o96pRwk%YJq5pi0ahd(azM31)m}ZmoIP zTAn>++Mr5CAAW}#!!ZTs}TseKKOijAm zUe3*^r>__G@YBuH8?6ZHYDlz(Dd=C;|-3Aja^|Rz3IBDPOAUpsK{>J Fe*p^E&j0`b delta 2528 zcmbVOO>7fa5Z-5dcWtlNUMG&@p9H&2LfAkZhhLfSlaP`?)FeoYOKAhfKU>G(*zQ{g zMYIr9sVEewRrC&RTB%4?tBPLQDu=3<-e`M_s#eeyC>(l0JwOCiDo%Z~8z(>mifSoe zW@cyh&Aj>EoBd-*Kj3~KicW_9-k(h6{|wH!18B=kd#5|f1eg~Y#TH@|b`+6bpKoT~ zAvz5sM~(cdQ80{lYILj^XTIThC$$JQi-&hnRjjEF(QQPzsnN4y40-aB?7a)=$Vg}3 zEaP$QE&`1spQ53;d*}}0d{oB`kq54q%4Etn;5HwVd-=R08wL@#%=TWYOUsY-3l=X^O;%i=;N9aW3b3NGg+ zvehzP?(tVrBy$LYpSJ^caQL4)aE!)oA)CC(O*XId3U4-NmFH_viG1nZ-SKRu4?;2k zE%ZJSWBTIUi^adNqg$7>O5An-=`lKN|)eZWd+DeZc2T$*gCK9nk;*l*L zi+AZLuCrZn`n$&Bm7}QJw5nRst>c9fh4iFs(e2rEsanXTb2?YSDlP80{dB;B(9h)4 zCsi1p7|*EKJg3h;qAHDtasNb9L21r5w$v(L(90TB@co-R~n1kp)Q3 z%?9_Q!0RBx-dsbvwVXMv!AywaE^UM127 zRumPt;)z*-t<>5jHa6Q7N%1OmrcJ4j*|1CTVKLtz`}GhoxG^@QR?~Nl26*Yhx-FNk zs&s~oZfKfnhD=r{Y95?1uoVDK1DpXU0^|W!xUUQ4jHcqVX*iV27ZY`mZFHKd*|9W! z3*0LJR{+eb%KgM;O&MTL$Q5p{Qd@VtO!G83jo}3_l-6^5Pg6grR(qFhjkIoDAEik$ zvZLR@u0dcIvZs^AYWK;-B@4Rrc1t$qT4eOQ*rPi@;y>W-muPA&G+4;J(D0Y)Y^=8$p6o&wc) z+mj<#x9=IJL!_wg!-TrP(prhaeJeufHWOH2PTXKlkleMGCT4&Lq+2#{tIE@`>p^0 diff --git a/Inventario/__pycache__/models.cpython-313.pyc b/Inventario/__pycache__/models.cpython-313.pyc index 69f475c025c003b9dd32eaafbd8f165eef38c8d9..f31d56eb99a786beb50e897928a490ef4b2762fe 100644 GIT binary patch literal 7495 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 diff --git a/Inventario/__pycache__/views.cpython-313.pyc b/Inventario/__pycache__/views.cpython-313.pyc index 7fdd3c45c3205154c2b5db8e1689943348fa6fa8..46650bf728f3d508064bc8bbb46a8e1dc8abe914 100644 GIT binary patch delta 5697 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 delta 6215 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 diff --git a/Inventario/forms.py b/Inventario/forms.py index 2d57d19..1c0b469 100644 --- a/Inventario/forms.py +++ b/Inventario/forms.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'}), + } diff --git a/Inventario/migrations/0004_remove_inventario_precio_and_more.py b/Inventario/migrations/0004_remove_inventario_precio_and_more.py new file mode 100644 index 0000000..7233ff5 --- /dev/null +++ b/Inventario/migrations/0004_remove_inventario_precio_and_more.py @@ -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')), + ], + ), + ] diff --git a/Inventario/migrations/__pycache__/0004_remove_inventario_precio_and_more.cpython-313.pyc b/Inventario/migrations/__pycache__/0004_remove_inventario_precio_and_more.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd430dacbb01e112dfbbacc241c0b65b89446599 GIT binary patch literal 2486 zcmcguPi)gx77TSIDW#+p;ZI-;77P!vxDq>T;P2g7_z)lF=r_ulefh{h`yrmKvX#_8S%i=B!+eYj@^LN*9^Qm7 z@}CjL2Kr(6BY-e5P&Nz^BsjVk!Q?=lB%cEN%s`oIKgy5s<6P(>{Z>B{TmUrEfOK>a z(xn~~bSB?;-eKO)*_7uk^H#lS{wNm&v@B@N4Dtw(&v-EnfyV40jcT%zd!1iN4B#yc z;GKM(#~iUDmt_b*EBL#U>&l zZyg6%xhaD)O*mx2_VGyEHwK5z78ZAC2yn-}5?1p;G9m$PQ&fbOBG!=(7l8O!fVgBs z2l%$4$+^bQD2RR2NO%c@%JnF{kPH)e@p&6pGC{BYmm5B1CJdM600H|ytwiwqX&g6 z^iv3ji)g9oV32MOKljxnc>mkSZayE+ZYog-em)iq}NTUK!YuBzZd=a%Hiy zUrJvXEhz@V{ytuYWUtCii;71W{=}PqzsD@r$$D&%VmXW?;Xszla4R7czXw7O#Sr-qIT|Klt_-0jM z&@T1|P2L|Lq1P^=DnarwDzr8+175wwomc(407ZR6?J`v4 zW@ozT6W!$0t8g$9-DMAP3;*Iy+w62VeY~5T?WQK3)V!UV-@5zrg_mV3b@$a!2&{d~ zeZ6CE*UQ>$wwneolb+s!om$u`ZyQ#sd>GA(Fgf{qa{Ot>NuRRQr?x{cbLN_0s@O{F zX2Jk~=L=4zU}p;3Wh+xM6N}yC^z(a8_OhM5{7d$VnYh|b&b?T6az#5=+?Gs!)fDUI z1J%lDW}?-zKWk^sZk1mq%}+nGGHYhyb2#XW1!wMpJ$GSy%$mDqCO+ul7VKbEePO(`U9iKWu)#=@f5R#T!oXj#a$l z6z^Nb`{oxdYx<#?z`M!F*vPAJ408C+e2V${CNA|0m}kh8--!jOR`CC{6#DImue#k8 z*_V4`Zf2`@TP%*YI^9p(!Z+7%aQNKp?QkP=VvWQ78XoP6wE$Q74hJ M61l%9AUuG70F;+-O8@`> literal 0 HcmV?d00001 diff --git a/Inventario/models.py b/Inventario/models.py index c0078ce..9ee72c7 100644 --- a/Inventario/models.py +++ b/Inventario/models.py @@ -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) diff --git a/Inventario/templates/Base.html b/Inventario/templates/Base.html index 29657a7..ac73800 100644 --- a/Inventario/templates/Base.html +++ b/Inventario/templates/Base.html @@ -12,13 +12,13 @@