Update Product Quantity

Hello,

I am relatively new to Django and this is my first post here. This is also my first real project with Django.

I want to be able to update the quantity of product whenever items are received or sold. I used Class Based Views.
I have tried to implement the various methods of doing this I found on the internet. None worked for me.
I just had to come here to seek for help.

Thanks in advance for any help.

Here are my respective models:

Product

from django.db import models
from datetime import datetime
from django.urls import reverse
from pharmacycategory.models import TblPharmacyCategory
from pharmacybrand.models import TblPharmacyBrand
from pharmacydepartment.models import TblPharmacyDepartment
from pharmacypresentation.models import TblPharmacyPresentation
from tariff.models import TblTariff


class TblPharmacyProduct(models.Model):
    date = models.DateField(default=datetime.now, blank=False)
    item = models.ForeignKey(TblTariff, on_delete = models.CASCADE,null=True, blank=True )
    category = models.ForeignKey(TblPharmacyCategory, on_delete=models.CASCADE)
    brand = models.ForeignKey(TblPharmacyBrand, on_delete = models.CASCADE,null=True, blank=True )
    department = models.ForeignKey(TblPharmacyDepartment, on_delete = models.CASCADE,null=True, blank=True )
    presentation = models.ForeignKey(TblPharmacyPresentation, on_delete = models.CASCADE,null=True, blank=True )
    unitpack = models.IntegerField(default=0)
    quantity = models.IntegerField(default=0)
    unitcost = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    unitprice = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    reorderlevel = models.IntegerField(default=0)
    reorderquantity = models.IntegerField(default=0)
    expirydate = models.DateField(default=datetime.now, blank=False)
    notes = models.TextField()

    def __str__(self):
        return str(self.item)

    class Meta:
        db_table = 'tblpharmacyproduct'
        ordering = ['department']   

    #objects = models.Manager()
    #broswer = ProductManager()        
     
    def get_absolute_url(self):
        return reverse('pharmacyproduct:pharmacyproduct-detail', kwargs={'pk': self.pk})

Sales

from django.db import models
from datetime import datetime
from django.urls import reverse
from pharmacyproduct.models import TblPharmacyProduct
#from django.db.models.signals import post_delete
#from django.dispatch import receiver


class TblPharmacySales(models.Model):
    date = models.DateField(default=datetime.now, blank=False)
    invoiceno = models.CharField(max_length=20, null=True, blank=True)
    hospitalno = models.CharField(max_length=20, null=True, blank=True)
    patient = models.CharField(max_length=100, null=True, blank=True)
    item = models.ForeignKey(TblPharmacyProduct, on_delete = models.CASCADE)
    quantity = models.IntegerField(default=0)
    unitprice = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    discount = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    amountreceived = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
        
    def __str__(self):
        return self.item

    class Meta:
        db_table = 'tblpharmacysales'
        ordering = ['item']   

    def get_absolute_url(self):
        return reverse('pharmacysales:pharmacysales-detail', kwargs={'pk': self.pk})

Receives (Purchases)

from django.db import models
from datetime import datetime
from django.urls import reverse
from pharmacyproduct.models import TblPharmacyProduct


class TblPharmacyReceives(models.Model):
    date = models.DateField(default=datetime.now, blank=False)
    supplier = models.CharField(max_length=20, null=True, blank=True)
    invoiceno = models.CharField(max_length=20, null=True, blank=True)
    item = models.ForeignKey(TblPharmacyProduct, on_delete = models.CASCADE)
    quantity = models.IntegerField(default=0)
    unitcost = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    unitprice = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    expirydate = models.DateField(default=datetime.now, blank=False)
     
    def __str__(self):
        return self.item

    class Meta:
        db_table = 'tblpharmacyreceives'
        ordering = ['item']   

    def get_absolute_url(self):
        return reverse('pharmacyreceives:pharmacyreceives-detail', kwargs={'pk': self.pk})

Thanks for posting your models. Now if you would post one of your views where you’re trying to do this, we might be able to help you with that.
In one of the common cases when creating a custom UpdateView, you would want to do that kind of work in your form_valid method.

Hello KenWhitesell,

Thank you for your response.

Here is my view, showing what I wanted to do. I placed the pharmacysales_issueditem method
under the class PharmacySalesCreate(CreateView):

from pharmacyproduct.models import TblPharmacyProduct
from django.shortcuts import render, redirect  
from django.urls import reverse_lazy
from django.views.generic import ListView
from django.views.generic.edit import CreateView, DeleteView, UpdateView, FormView
from django.views.generic.detail import DetailView
from pharmacysales.forms import FrmPharmacySales  
from pharmacysales.models import TblPharmacySales 
from django.db.models import Sum
from slick_reporting.views import SlickReportView
from django.db import transaction


class TotalProductSales(SlickReportView):
    # The model where you have the data
    report_model = TblPharmacySales
    # the main date field used for the model.
    date_field = 'date' # or 'order__date_placed'
    # this support traversing, like so
    # date_field = 'order__date_placed'
    # A foreign key to group calculation on
    group_by = 'item'
    # The columns you want to display
    #columns = ['patient', '__total_quantity__']
    columns = ['item', 'quantity']
    # Charts
    charts_settings = [
    {
    'type': 'bar',
    'data_source': '__total_quantity__',
    'title_source': 'patient',
    },
]


class PharmacySalesList(ListView):
    model = TblPharmacySales 
    template_name = 'pharmacysales/pharmacysales_list.html'
    context_object_name = 'pharmacysales_list'


class PharmacySalesCreate(CreateView):
    model = TblPharmacySales
    template_name = 'pharmacysales/pharmacysales_create.html'
    fields = [
             'date', 
             'invoiceno',
             'hospitalno',
             'patient',
             'item',
             'quantity',
             'unitprice',
             'discount',
             'amountreceived',
        ]
    
    @transaction.atomic
    def pharmacysales_issueditem(request, pk):
        issued_item = TblPharmacyProduct.objects.get(id = pk)
        sales_form = FrmPharmacySales(request.POST)  

        if request.method == 'POST':     
            if sales_form.is_valid():
                new_sale = sales_form.save(commit=False)
                new_sale.item = issued_item
                new_sale.unitprice = issued_item.unit_price   
                new_sale.save()
                #To keep track of the stock remaining after sales
                issued_quantity = int(request.POST['quantity'])
                issued_item.quantity -= issued_quantity
                issued_item.save()

                print(issued_item.item_name)
                print(request.POST['quantity'])
                print(issued_item.total_quantity)

                return redirect('receipt') 

        return render (request, 'prpharmacysales/pharmacysales_create.html',
        {
        'sales_form': sales_form,
        })

    success_url = reverse_lazy('pharmacysales:pharmacysales-list')    
   

class PharmacySalesUpdate(UpdateView):
    model = TblPharmacySales
    template_name = 'pharmacysales/pharmacysales_update.html'
    fields = [
             'date', 
             'invoiceno',
             'hospitalno',
             'patient',
             'item',
             'quantity',
             'unitprice',
             'discount',
             'amountreceived',
        ]
    
    success_url = reverse_lazy('pharmacysales:pharmacysales-list')


class PharmacySalesDelete(DeleteView):
    model = TblPharmacySales
    template_name = 'pharmacysales/pharmacysales_delete.html'
    fields = [
             'date', 
             'invoiceno',
             'hospitalno',
             'patient',
             'item',
             'quantity',
             'unitprice',
             'discount',
             'amountreceived',
        ]
      
    success_url = reverse_lazy('pharmacysales:pharmacysales-list')


class PharmacySalesDetail(DetailView):
    model = TblPharmacySales
    template_name = 'pharmacysales/pharmacysales_detail.html'
    context_object_name = 'pharmacysales_list' 


class PharmacySalesForm(FormView): 
    form_class = FrmPharmacySales 
    template_name = "pharmacysales/pharmacysales_form.html"
    success_url = reverse_lazy('pharmacysales:pharmacysales-list')

Here is my Form

from django.forms import ModelForm
from pharmacysales.models import TblPharmacySales

class FrmPharmacySales(ModelForm):
    class Meta:
        model = TblPharmacySales
        fields = '__all__'

You don’t get to arbitrarily name methods within the CBVs. A CBV defines a set of methods that are called in a specific sequence to return a response.
Your ability to modify what a CBV does, is limited to overriding those methods. (You may add other methods to be called from those methods, but those predefined methods are your starting point.)

I suggest you reread the docs for the Generic CBVs, along with taking a look at the Classy Class Based View docs and the CBV diagrams page to get a better understanding of how the CBVs work.