# How to recalculate a field in another model based on the calculations of one model in Django?

## Issue

There are three models in my project, that are:

```
class Package(models.Model):
patient=models.ForeignKey(Patient, on_delete=CASCADE)
diagnosis=models.ForeignKey(Diagnosis, on_delete=CASCADE)
treatment=models.ForeignKey(Treatment, on_delete=CASCADE)
patient_type=models.ForeignKey(PatientType, on_delete=CASCADE)
date_of_admission=models.DateField(default=None)
max_fractions=models.IntegerField(default=None)
total_package=models.DecimalField(max_digits=10, decimal_places=2)
class Receivables(models.Model):
patient=models.ForeignKey(Patient, on_delete=CASCADE)
pattern = RegexValidator(r'(RT|rt|rT|Rt)\/[0-9]{4}\/[0-9]{2}\/[0-9]{4}', 'Enter RT Number properly!')
rt_number=models.CharField(max_length=15, validators=[pattern])
discount=models.DecimalField(max_digits=9, decimal_places=2, default=0)
approved_package=models.DecimalField(max_digits=10, decimal_places=2, default=0)
proposed_fractions=models.IntegerField()
done_fractions=models.IntegerField()
base_value=models.DecimalField(max_digits=10, decimal_places=2, blank=True)
expected_value=models.DecimalField(max_digits=10, decimal_places=2, blank=True)
@property
def package(self):
try:
return Package.objects.filter(patient=self.patient).order_by('-id').first()
except Package.DoesNotExist:
return None
def calculate_approved_discount(self):
if(self.package):
if self.package.patient_type=='CASH':
self.approved_package = self.package.total_package - self.discount
else:
pass
def calculate_base_value(self):
if (self.package):
process_charge=self.package.total_package*15/100
net_total_package=self.package.total_package - process_charge
amount_per_fraction=net_total_package/self.package.max_fractions
net_cost=amount_per_fraction*self.done_fractions
gross_cost=net_cost+process_charge
self.base_value=gross_cost
else:
self.base_value=self.approved_package
def calculate_expected_value(self): #Edited
if not self.expected_value < 0:
if (self.package):
if self.base_value<self.approved_package:
self.expected_value=self.base_value
else:
self.expected_value=self.approved_package
else:
self.expected_value=0
else:
return abs(self.expected_value)
def save(self, *args, **kwargs):
self.calculate_approved_discount()
self.calculate_base_value()
self.calculate_expected_value()
super(Receivables, self).save(*args, **kwargs)
class Realization(models.Model):
patient=models.ForeignKey(Patient, on_delete=CASCADE)
cash=models.BooleanField(default=False)
amount_received=models.DecimalField(max_digits=10, decimal_places=2, default=0)
billing_month=models.DateField(default=None)
deficit_or_surplus_amount=models.DecimalField(max_digits=8, decimal_places=2, blank=True)
deficit_percentage=models.FloatField(blank=True, default=0)
surplus_percentage=models.FloatField(blank=True, default=0)
remarks=models.TextField(max_length=500, default="N/A")
@property
def receivables(self):
try:
return Receivables.objects.filter(patient=self.patient).order_by('-id').first()
except Receivables.DoesNotExist:
return None
@property
def discharge(self):
try:
return Discharge.objects.filter(patient=self.patient).order_by('-id').first()
except Discharge.DoesNotExist:
return None
@property
def package(self):
try:
return Package.objects.filter(patient=self.patient).order_by('-id').first()
except Package.DoesNotExist:
return None
def calculate_deficit_surplus_amount(self):
if (self.receivables):
print(self.receivables)
self.deficit_or_surplus_amount=self.amount_received-self.receivables.expected_value
else:
self.deficit_or_surplus_amount=0
def calculate_deficit_or_surplus_percentage(self):
if (self.receivables):
if self.amount_received>self.receivables.expected_value:
self.surplus_percentage=self.deficit_or_surplus_amount/self.receivables.expected_value*100
self.deficit_percentage=0
elif self.amount_received<self.receivables.expected_value:
self.deficit_percentage=self.deficit_or_surplus_amount/self.receivables.expected_value*100
self.surplus_percentage=0
elif self.amount_received==self.receivables.expected_value:
self.deficit_percentage=0
self.surplus_percentage=0
else:
self.surplus_percentage=0
self.deficit_percentage=0
def save(self, *args, **kwargs):
self.calculate_deficit_surplus_amount()
self.calculate_deficit_or_surplus_percentage()
super(Realization, self).save(*args, **kwargs)
```

**EDIT:**

Now what I want is when a patient is paying the amount and if there is deficit (which is contained by deficit_or_surplus_amount), I want that deficit amount to be saved in the expected_value of Receivables, so that when we reclaim the amount, the further calculations would be based on that expected_value, when we do receive the deficit amount.

I don’t want to delete the previous instances but rather create a new instance of Receivables that has a new expected_value which now carries what was paid less the last time. So we expect that amount from the patient. So when the patient pays the next time, the deficit or surplus would be calculated on the basis of what was expected of him to pay this time.

For example:

If a patient gets admitted and has a Government scheme pay for him. Suppose the total expected_value is 75000 from him. He gets discharged and the we claim the amount to the Government. When we receive the amount, we get less amount, let’s say we received only 70000. So 5000 deficit. We reclaim the repudiated amount. Now we expect to receive 5000 from the Government, not 75000. So if we receive the amount from the scheme and it is not 5000, instead it’s only 2500, so the Realization table’s methods should be able to calculate the deficits or surpluses based on the now expected_value, i.e, 5000.

I hope my question is clear now. If you still want further explanation , please let me know.

I tried to use a signal for this purpose:

```
@receiver(post_save, sender=Realization)
def new_receivable_save(sender, instance, created, **kwargs):
pkg=Package.objects.filter(patient=instance.patient).order_by('-id').first()
rec=Receivables.objects.filter(patient=instance.patient).order_by('-id').first()
if created:
if pkg.patient_type!='CASH':
if instance.deficit_or_surplus_amount<0:
Receivables(
patient=rec.patient,
rt_number=rec.rt_number,
discount=rec.discount,
approved_package=rec.approved_package,
proposed_fractions=rec.proposed_fractions,
done_fractions=rec.done_fractions,
base_value=rec.base_value,
expected_value=abs(instance.deficit_or_surplus_amount)
).save()
```

This function does create a new instance of `Receivables`

but with the previous `expected_value`

and not the recalculated one.

Where am I going wrong? How should I go about that? Thanks in advance.

## Solution

You are saving the `deficit`

amount correctly every time.

But you are not saving/updating the `expected_value`

at all.

The first time you are saving the `expected_value`

from `base_value`

which is correct.

The next time amount received you have to update the `expected_value`

(It has to be 5000, 2500).

- 75000
`base_value`

, 75000`expected_value`

. - 70000
`amount_received`

– 5000`deficit`

– 5000`expected_value`

. - 2500
`amount_received`

– 2500`deficit`

– 2500`expected_value`

. - 1300
`amount_received`

– 1200`deficit`

– 1200`expected_value`

.

Here you are doing `amount_received`

– previous `expected_value`

(70000 – 75000 = -5000). You are doing in a negative/reverse way. Thats fine.

But `Receivables`

model has `save()`

which contains `calculate_expected_value`

```
def calculate_expected_value(self):
if (self.package):
if self.base_value<self.approved_package:
self.expected_value=self.base_value
else:
self.expected_value=self.approved_package
else:
self.expected_value=0
```

This method is overriding the `expected_value`

in this model. It is not taking the passing expected value while initializing the `Receivables(....).save()`

object.

Try modify above method like this:

```
def calculate_expected_value(self):
if not self.expected_value < 0: # try something here, if expected value exists already while saving, we don't reassign it below.
if (self.package):
if self.base_value<self.approved_package:
self.expected_value=self.base_value
else:
self.expected_value=self.approved_package
else:
self.expected_value=0
```

This is where you might be going wrong. Please correct me if I am wrong.

EDIT:

```
def calculate_expected_value(self): #Edited
if not self.expected_value < 0:
if (self.package):
if self.base_value<self.approved_package:
self.expected_value=self.base_value
else:
self.expected_value=self.approved_package
else:
self.expected_value=0
else:
exp_value = self.expected_value * -1
return exp_value
```

Answered By – Siva Sankar

**This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 **