como aumentar y disminuir un stock

915 views
Skip to first unread message

wilder Hernández Garcia

unread,
Mar 15, 2015, 2:37:03 PM3/15/15
to djan...@googlegroups.com
Estoy haciendo un proyecto para una farmacia y, tengo las tablas Productos y DetalleVenta, la pregunta es al hacer una venta se descuente el stock automaticamente, no se como hacerlo, les agradecería muchos sus comentarios..!

class Producto(models.Model):
    codigo = models.CharField(max_length=10, unique=True)   
    nombre = models.CharField(max_length=200, unique=True)
    descripcion = models.TextField(max_length=400)
    categoria = models.ForeignKey(Categoria)
    precio_compra = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    stock = models.IntegerField()

    def __unicode__(self):
        return self.nombre

    def preeciototal(self):
        precio_total=self.precio_compra*self.stock       
        return precio_total



class DetalleVenta(models.Model):
   
    codigo = models.CharField(max_length=10, unique=True)
    producto = models.ForeignKey(Producto)   
    cantidad = models.IntegerField()   
    precio_venta = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    def __unicode__(self):
        return u'%s' % (self.producto)


he realizado en la termial: shell
>>> product = Producto.objects.get(nombre='panadol')
>>> product.stock -= 1
>>> product.save()


no se como hacer que descuente automaticamente cuando hago una venta.

Julián Cortés

unread,
Mar 15, 2015, 3:16:56 PM3/15/15
to djan...@googlegroups.com
se hace justamente así como lo está haciendo en la shell.

--
--
Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del Framework Django de habla hispana" de Grupos de Google.
Si quieres publicar en este grupo, envía un mensaje de correo
electrónico a djan...@googlegroups.com
Para anular la suscripción a este grupo, envíe un mensaje a django-es-...@googlegroups.com
Para obtener más opciones, visita este grupo en http://groups.google.com.bo/group/django-es.
---
Has recibido este mensaje porque estás suscrito al grupo "Django-es" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
           pity

01110000 01101001 01110100 01111001

Google+: +JuliánCortés
Twitter: __pity7736__

Juan Marcelo Leiva Sandoval

unread,
Mar 15, 2015, 3:34:41 PM3/15/15
to djan...@googlegroups.com
Podrías actualizar el stock en el metodo save() al generar una venta o crear un signal. 

Saludos 
--
--
Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del Framework Django de habla hispana" de Grupos de Google.
Si quieres publicar en este grupo, envía un mensaje de correo
electrónico a djan...@googlegroups.com
Para anular la suscripción a este grupo, envíe un mensaje a django-es-...@googlegroups.com
Para obtener más opciones, visita este grupo en http://groups.google.com.bo/group/django-es.
---
Has recibido este mensaje porque estás suscrito al grupo "Django-es" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.


--
Marcelo Leiva Sandoval
Ing. (e) Computación e Informática
Django & Symfony2 Developer
Linux User #491264

"Los que aseguran que es imposible no deberian interrumpir a los que estamos intentándolo". Thomas A. Edison.

wilder Hernández Garcia

unread,
Mar 15, 2015, 3:54:56 PM3/15/15
to djan...@googlegroups.com
como lo aria que el uno sea la cantidad de la tabla Detalle_venta, en la view, gracias. o se puede hacer en el models cuando se guardar una venta disminuya el stock...?


>>> product = Producto.objects.get(nombre='panadol')
>>> product.stock -= 1
>>> product.save()
Has recibido este mensaje porque estás suscrito a un tema del grupo "Django-es" de Grupos de Google.
Para anular la suscripción a este tema, visita https://groups.google.com/d/topic/django-es/COTvnQExH7M/unsubscribe.
Para anular la suscripción a este grupo y a todos sus temas, envía un correo electrónico a django-es+...@googlegroups.com.

Jose Regalado

unread,
Mar 16, 2015, 1:32:25 AM3/16/15
to djan...@googlegroups.com
NO será mejor, decirle al gestor de Bd (que no sea sqlite xD), que lo
haga?, sin complicarse?

El día 15 de marzo de 2015, 15:24, wilder Hernández Garcia
José Luis Regalado
bashman
Linux User nº 280381
WhatsApp / Telegram +58 416 1705119

Juan Ignacio

unread,
Mar 16, 2015, 8:13:48 AM3/16/15
to djan...@googlegroups.com
Puedes hacer un trigger en la base de datos, o usar los signals de Django:

<https://docs.djangoproject.com/en/1.7/topics/signals/>

Cualquier de los dos métodos está bien, y los dos tienen sus ventajas y sus inconvenientes. Yo personalmente optaría por el trigger, si fuera posible.

Para obtener más opciones, visita https://groups.google.com/d/optout.



--
Juan Ignacio Rodríguez de León
Móvil: 605 890514
E-Mail: euri...@gmail.com
http://www.elornitorrincoenmascarado.com/
http://descon2.com/

wilder Hernández Garcia

unread,
Mar 16, 2015, 10:10:49 AM3/16/15
to djan...@googlegroups.com
Esto es el trigger, en msql, funcionara en posgress o en sqlite..

CREAR TRIGGER PARA LA SALIDA DE PRODUCTOS

create trigger Salida_Productos
after insert on detalle_venta

for each row
   
    update producto set stock= stock - NEW.cantidad
   
    where producto.id=NEW.id

Hiko hitokiri

unread,
Mar 16, 2015, 10:15:57 AM3/16/15
to djan...@googlegroups.com
no necesitas hacer un triger simplemente extiende la funcion save de tu modelo para hacer la acción de disminución desde ahi

wilder Hernández Garcia

unread,
Mar 16, 2015, 10:25:09 AM3/16/15
to djan...@googlegroups.com
Primeramente Agradecerles por las respuestas, ando días investigando y no tengo respuestas, Hiko hitokiri, tienes algún ejemplo o algún manual para guiarme te lo agradecería bastante.

El 16 de marzo de 2015, 9:15 a. m., Hiko hitokiri<las...@gmail.com> escribió:
no necesitas hacer un triger simplemente extiende la funcion save de tu modelo para hacer la acción de disminución desde ahi

--

Hiko hitokiri

unread,
Mar 16, 2015, 10:43:26 AM3/16/15
to djan...@googlegroups.com
es justo como lo pusiste vos en la shell capturas el self.id de el objeto  sacas el slef.cantidad y se lo reduces al producto en el metodo save
save

wilder Hernández Garcia

unread,
Mar 16, 2015, 10:44:51 AM3/16/15
to djan...@googlegroups.com
lo voy a intentar hacer.. gracias.

El 16 de marzo de 2015, 9:42 a. m., Hiko hitokiri<las...@gmail.com> escribió:
es justo como lo pusiste vos en la shell capturas el self.id de el objeto  sacas el slef.cantidad y se lo reduces al producto en el metodo save
save

--

Phoenix

unread,
Mar 17, 2015, 9:18:59 AM3/17/15
to djan...@googlegroups.com
Che, cuanto delirio, no se compliquen la vida con la base de datos, para que usan un framework? Un salvavidas de plomo le tiraron jajajaja. 
Hay patrones y buenas prácticas por las que medianamente se deben guiar y si no las conocen, por el sentido común. Y esto es programación orientada a objetos vean los patrones GRASP, está por ejemplo el patrón "experto en información", que es un ppio básico de asignación de responsabilidades, te dicen quien debe hacer algo, también el bajo acoplamiento y la alta cohesión para que sepas también quien no debe hacerlo, (en este caso la base de datos)
Te faltaría una tabla Venta que agrupe los DetalleVenta, redefiní el método save de la tabla Venta y ahí bajás el stock. Te recomendaría también que hagas todo dentro de una transacción así no tenés que hacer ningun maneje raro si la operación falla como por ejemplo incrementar el stock.

detalle.producto.stock -=detalle.cantidad
detalle.producto.save()

Los signals dejalos para mejores usos que este.
Otro consejo, a lo mejor lo pusiste como ejemplo, pero tenés que profundizar el modelo de datos, un producto tiene distintas presentaciones, entonces nombre no puede ser un índice. 
Nadie nace aprendido, y está bueno también más allá del lenguaje elegido, conocer algunas buenas prácticas en programación, se que es un garrón tener que aprender un lenguaje, aprender un framework y encima tener que leer sobre buenas prácticas, pero es la manera más fácil de programar , la que les va a dar mejores resultados en cuanto a calidad y menos dolores de cabeza.

Saludos

wilder Hernández Garcia

unread,
Mar 17, 2015, 10:02:31 AM3/17/15
to djan...@googlegroups.com
Gracias por responder Phoenix, esto es mi base de datos.


# Create your models here.
class Categoria(models.Model):
    codigo = models.CharField(max_length=10, unique=True)   
    nombre = models.CharField(max_length=60)

    def __unicode__(self):
        return u'%s' % (self.nombre)


class Producto(models.Model):
    codigo = models.CharField(max_length=10, unique=True)   
    nombre = models.CharField(max_length=200, unique=True)
    descripcion = models.TextField(max_length=400)
    categoria = models.ForeignKey(Categoria)
    precio_compra = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
    stock = models.IntegerField()

    def __unicode__(self):
        return self.nombre

    def preeciototal(self):
        precio_total=self.precio_compra*self.stock       
        return precio_total



class DetalleVenta(models.Model):
   
    codigo = models.CharField(max_length=10, unique=True)
    producto = models.ForeignKey(Producto)   
    cantidad = models.IntegerField()   
    precio_venta = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    def __unicode__(self):
        return u'%s' % (self.producto)



class Venta(models.Model):

     codigo = models.CharField(max_length=10, unique=True)
     agregarProductos = models.ManyToManyField(DetalleVenta)
     fecha = models.DateTimeField()
     def __unicode__(self):
         return self.codigo



lo que me dices lo hago en la views o en el models, resien toy empezando a programar en django.. gracias e.

detalle.producto.stock -=detalle.cantidad
detalle.producto.save()





   

monoBOT

unread,
Mar 17, 2015, 10:10:57 AM3/17/15
to djan...@googlegroups.com
Hola, 
o lo haces reescribiendo el save del modelo de la venta:
o con un post_save signal:

Por supuesto que tambien puedes hacerlo como dice Juan Ignacio con triggers de la base de datos, pero es que Juan Ignacio es un poco hardcore XD, no te lo recomiendo porque si algún día tienes que modificar la lógica de negocio tienes que volver a tocar la base de datos, lo cual no es demasiado buena idea.



Has recibido este mensaje porque estás suscrito al grupo "Django-es" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+...@googlegroups.com.

Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
monoBOT
Visite mi sitio(Visit my site): monobotsoft.es/blog/

wilder Hernández Garcia

unread,
Mar 17, 2015, 10:23:03 AM3/17/15
to djan...@googlegroups.com
Gracias, lo intentare hacerlo, espero que me salga..xd

Cristián Gallo

unread,
Mar 17, 2015, 11:23:48 AM3/17/15
to djan...@googlegroups.com

Trata de hacer un método en la clase que te incremente o decremente el stock y ese método lo llamas en la vista

wilder Hernández Garcia

unread,
Mar 17, 2015, 11:30:28 AM3/17/15
to djan...@googlegroups.com
Estoy haciendo este ejemplo para aplicarlo en mi models.

class Product(models.Model):
     name = models.CharField(max_length=255)
     price = models.DecimalField(default=0.0, max_digits=9, decimal_places=2)
     stock = models.IntegerField(default=0)

     def  __unicode__(self):
         return self.name

class Cart(models.Model):
    customer = models.ForeignKey(Customer)
    products = models.ManyToManyField(Product, through='TransactionDetail')
    t_date = models.DateField(default=datetime.now())
    t_sum = models.FloatField(default=0.0)

    def __unicode__(self):
         return str(self.id)

class TransactionDetail(models.Model):
    product = models.ForeignKey(Product)
    cart = models.ForeignKey(Cart)
    amount = models.IntegerField(default=0)



pero me sale error: name 'post_save' is not defined


from django.db.models.signals import post_save

class TransactionDetail(models.Model):
    # ... fields here

# method for updating
def update_stock(sender, instance, **kwargs):
     instance.product.stock -= instance.amount
     instance.product.save()

# register the signal
post_save.connect(update_stock, sender=TransactionDetail, dispatch_uid="update_stock_count")

wilder Hernández Garcia

unread,
Mar 17, 2015, 11:51:21 AM3/17/15
to djan...@googlegroups.com
Ya lo soluicone era asi, al momento de hacer una transaccion en el admin se descuenta el stock, ahora  voy a empezar hacer en la view, luego para mostrar en el templates, adecuando a mis necesidades, Gracias a todos


def update_stock(sender, instance, **kwargs):
     instance.product.stock -= instance.amount
     instance.product.save()

# register the signal
signals.post_save.connect(update_stock, sender=TransactionDetail, dispatch_uid="update_stock_count")

wilder Hernández Garcia

unread,
Mar 17, 2015, 11:56:06 AM3/17/15
to djan...@googlegroups.com
Estara bien mi base de datos..?

from django.db import models
Gracias.

wilder Hernández Garcia

unread,
Mar 17, 2015, 1:43:06 PM3/17/15
to djan...@googlegroups.com
sobre el stock, esto es la solucion.


class DetalleVenta(models.Model):
   
    codigo = models.CharField(max_length=10, unique=True)
    producto = models.ForeignKey(Producto)   
    cantidad = models.IntegerField()   
    precio_venta = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    def __unicode__(self):
        return self.codigo

def update_stock(sender, instance, **kwargs):
    instance.producto.stock -= instance.cantidad
    instance.producto.save()

# register the signal
signals.post_save.connect(update_stock, sender=DetalleVenta, dispatch_uid="update_stock_count")


Rut Cortés

unread,
May 20, 2016, 6:46:41 PM5/20/16
to Django-es


El domingo, 15 de marzo de 2015, 15:37:03 (UTC-3), wilder Hernández Garcia escribió:

Rut Cortés

unread,
May 20, 2016, 6:46:41 PM5/20/16
to Django-es
Hola solucion funciona usando el admin, pero en mi template no lo resta al stock
La vista tengo esto:
def ventas_nuevo(request):
    formset = Detalle_VentaFormSet()
    form = VentaForm()
    

    if request.method == 'POST':
        venta = form.save(commit=False)
        formset = Detalle_VentaFormSet(request.POST or None, instance=venta,)

        if form.is_valid() and formset.is_valid():
            form = form.save()
            formset = formset.save()
            
            return HttpResponseRedirect('/operaciones/ventas/')
    else:
        form = VentaForm()
        formset = Detalle_VentaFormSet(instance=Venta())

    return render(request,'venta_form.html', {
        "form": form,
        "formset": formset
    })

Rut Cortés

unread,
May 20, 2016, 6:46:42 PM5/20/16
to Django-es
Yo estoy teniendo este mismo problema..resulta q desde el admin lo resta, pero por un lado si lo hago desde mi vista no hace nada..y por otro lado si elimino la operacion no se restaura el stock a la cantidad que tenia antes.. Mi codigo: Ayuda!
def ventas_nuevo(request):
    formset = Detalle_VentaFormSet()
    form = VentaForm()
    

    if request.method == 'POST':
        venta = form.save(commit=False)
        formset = Detalle_VentaFormSet(request.POST or None, instance=venta,)

        if form.is_valid() and formset.is_valid():
            form = form.save()
            formset = formset.save()
            
            return HttpResponseRedirect('/operaciones/ventas/')
    else:
        form = VentaForm()
        formset = Detalle_VentaFormSet(instance=Venta())

    return render(request,'venta_form.html', {
        "form": form,
        "formset": formset
    })

# method for updating
@receiver(post_save, sender=Detalle_Venta, dispatch_uid="actualizar_stock_cantidad")
def actualizar_stock(sender, instance, **kwargs):
    instance.producto.stock -= instance.cantidad
    instance.producto.save()  
        

El domingo, 15 de marzo de 2015, 15:37:03 (UTC-3), wilder Hernández Garcia escribió:

Francisco R. Del Roio

unread,
May 23, 2016, 8:42:54 AM5/23/16
to djan...@googlegroups.com
hola,

Según la documentación, que las funciones pasen por el recolector de
basura puede dar problemas. Además, recomienda importar el módulo que
contiene las señales en la función ready de tu aplicación.

Cito:
> In practice, signal handlers are usually defined in a signals
submodule of the application they relate to. Signal receivers are
connected in the ready() method of your application configuration class.
If you’re using the receiver() decorator, simply import the signals
submodule inside ready().

Fijate si estás haciendo así, asegurate de que tus señales se registren
correctamente y del modo apropiado.

Otra cosa, creo que si tenés que modificar alguna vez el registro del
detalle de venta vas a tener problemas para calcular el stock, por tanto
te diría que hagas correr un proceso sobre todos los registros de la
tabla para calcular el stock de cero, aunque sería algo caro en temas de
procesamiento...
> *he realizado en la termial: shell*
> >>> product = Producto.objects.get(nombre='panadol')
> >>> product.stock -= 1
> >>> product.save()
>
>
> no se como hacer que descuente automaticamente cuando hago una venta.
>
> --
> --
> Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios
> del Framework Django de habla hispana" de Grupos de Google.
> Si quieres publicar en este grupo, envía un mensaje de correo
> electrónico a djan...@googlegroups.com
> Para anular la suscripción a este grupo, envíe un mensaje a
> django-es-...@googlegroups.com
> Para obtener más opciones, visita este grupo en
> http://groups.google.com.bo/group/django-es.
> ---
> Has recibido este mensaje porque estás suscrito al grupo "Django-es" de
> Grupos de Google.
> Para anular la suscripción a este grupo y dejar de recibir sus mensajes,
> envía un correo electrónico a django-es+...@googlegroups.com
> <mailto:django-es+...@googlegroups.com>.
> Para acceder a más opciones, visita https://groups.google.com/d/optout.

--
¡Cuando tus fuerzas terminan, las de Dios comienzan!

Cristián Gallo

unread,
May 23, 2016, 9:52:53 AM5/23/16
to djan...@googlegroups.com
Hola, dos cosas, primero, se te va a restar si usas post_delete no post_save.
Yo no te recomendaría que uses esto para manejar el stock, digamos cual es la justificación? Porque no redefinís los métodos save y delete y ponés transacciones?
Esto se usa cuando necesitas cierta asincronía, por ejemplo necesitas disparar un proceso segundos después de haber guardado o borrado algo, digo para que perder tanto tiempo con esto si no te da ninguna utilidad extra?
En el método save de la venta deberías generar los detalles de venta, descontar stock todo dentro de una misma transacción.

--- Has recibido este mensaje porque estás suscrito a un tema del grupo "Django-es" de Grupos de Google.
Para anular la suscripción a este tema, visita https://groups.google.com/d/topic/django-es/COTvnQExH7M/unsubscribe.
Para anular la suscripción a este grupo y a todos sus temas, envía un correo electrónico a django-es+...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/d/optout.



--
Cristián M. Gallo
ma...@cristiangallo.com.ar

Ricardo Daniel Quiroga

unread,
May 23, 2016, 5:39:51 PM5/23/16
to Grupo Django-Es
hola 
lo que podes hacer es manejar la idea de Movimientos, una venta seria una Salida mientras que una compra a proveedor entrada de los mismos, y bueno el stock se calcule en base a sumar entradas - menos salidas y te daria el stock disponible. Esto sirve bastante ya que despues con ello podes calcular facilmente el valor real de el stock disponible (valor segun precio de compra no precio actual) segun politicas FIFO o LIFO

saludos

Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--

Ricardo Daniel Quiroga

Reply all
Reply to author
Forward
0 new messages