# Path: invoicing/models.py
# class Item(models.Model):
#     WEIGHT = [(i, i) for i in range(0, 20)]
#     UNIT_EMPTY = 'EMPTY'
#     UNIT_PIECES = 'PIECES'
#     UNIT_HOURS = 'HOURS'
#     UNITS = (
#         (UNIT_EMPTY, ''),
#         (UNIT_PIECES, _(u'pcs.')),
#         (UNIT_HOURS, _(u'hours'))
#     )
# 
#     invoice = models.ForeignKey(Invoice, verbose_name=_(u'invoice'), on_delete=models.CASCADE)
#     title = models.TextField(_(u'title'))
#     quantity = models.DecimalField(_(u'quantity'), max_digits=10, decimal_places=3, default=1)
#     unit = models.CharField(_(u'unit'), choices=UNITS, max_length=64, default=UNIT_PIECES)
#     unit_price = models.DecimalField(_(u'unit price'), max_digits=10, decimal_places=2)
#     discount = models.DecimalField(_(u'discount (%)'), max_digits=4, decimal_places=1, default=0)
#     tax_rate = models.DecimalField(_(u'tax rate (%)'), max_digits=3, decimal_places=1, help_text=_(u'VAT rate'),
#         blank=True, null=True, default=None)
#     tag = models.CharField(_(u'tag'), max_length=128,
#         blank=True, null=True, default=None)
#     weight = models.IntegerField(_(u'weight'), choices=WEIGHT, help_text=_(u'ordering'),
#         blank=True, null=True, default=0)
#     created = models.DateTimeField(_(u'created'), auto_now_add=True)
#     modified = models.DateTimeField(_(u'modified'), auto_now=True)
#     objects = ItemQuerySet.as_manager()
# 
#     class Meta:
#         db_table = 'invoicing_items'
#         verbose_name = _(u'item')
#         verbose_name_plural = _(u'items')
#         ordering = ('-invoice', 'weight', 'created')
# 
#     def __str__(self):
#         return self.title
# 
#     def get_absolute_url(self):
#         return getattr(settings, 'INVOICING_INVOICE_ITEM_ABSOLUTE_URL', lambda item: '')(self)
# 
#     @property
#     def subtotal(self):
#         subtotal = round(self.unit_price * self.quantity, 2)
#         return round(Decimal(subtotal) * Decimal((100 - self.discount) / 100), 2)
# 
#     @property
#     def discount_amount(self):
#         subtotal = round(self.unit_price * self.quantity, 2)
#         return round(Decimal(subtotal) * Decimal(self.discount / 100), 2)
# 
#     @property
#     def vat(self):
#         return round(self.subtotal * Decimal(self.tax_rate)/100 if self.tax_rate else 0, 2)
# 
#     @property
#     def unit_price_with_vat(self):
#         tax_rate = self.tax_rate if self.tax_rate else 0
#         return round(Decimal(self.unit_price) * Decimal((100 + tax_rate) / 100), 2)
# 
#     @property
#     def total(self):
#         return round(self.subtotal + self.vat, 2)
# 
#     def save(self, **kwargs):
#         # If tax rate is not set while creating new invoice item, set it according billing details
#         if self.tax_rate in EMPTY_VALUES and self.pk is None:
#             self.tax_rate = self.invoice.get_tax_rate()
#         return super(Item, self).save(**kwargs)


from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from invoicing.models import Item


@receiver(post_save, sender=Item)
@receiver(post_delete, sender=Item)
def recalculate(instance, **kwargs):
    invoice = instance.invoice
    invoice.total = invoice.calculate_total()

# Path: invoicing/models.py
# class Item(models.Model):
#     WEIGHT = [(i, i) for i in range(0, 20)]
#     UNIT_EMPTY = 'EMPTY'
#     UNIT_PIECES = 'PIECES'
#     UNIT_HOURS = 'HOURS'
#     UNITS = (
#         (UNIT_EMPTY, ''),
#         (UNIT_PIECES, _(u'pcs.')),
#         (UNIT_HOURS, _(u'hours'))
#     )
# 
#     invoice = models.ForeignKey(Invoice, verbose_name=_(u'invoice'), on_delete=models.CASCADE)
#     title = models.TextField(_(u'title'))
#     quantity = models.DecimalField(_(u'quantity'), max_digits=10, decimal_places=3, default=1)
#     unit = models.CharField(_(u'unit'), choices=UNITS, max_length=64, default=UNIT_PIECES)
#     unit_price = models.DecimalField(_(u'unit price'), max_digits=10, decimal_places=2)
#     discount = models.DecimalField(_(u'discount (%)'), max_digits=4, decimal_places=1, default=0)
#     tax_rate = models.DecimalField(_(u'tax rate (%)'), max_digits=3, decimal_places=1, help_text=_(u'VAT rate'),
#         blank=True, null=True, default=None)
#     tag = models.CharField(_(u'tag'), max_length=128,
#         blank=True, null=True, default=None)
#     weight = models.IntegerField(_(u'weight'), choices=WEIGHT, help_text=_(u'ordering'),
#         blank=True, null=True, default=0)
#     created = models.DateTimeField(_(u'created'), auto_now_add=True)
#     modified = models.DateTimeField(_(u'modified'), auto_now=True)
#     objects = ItemQuerySet.as_manager()
# 
#     class Meta:
#         db_table = 'invoicing_items'
#         verbose_name = _(u'item')
#         verbose_name_plural = _(u'items')
#         ordering = ('-invoice', 'weight', 'created')
# 
#     def __str__(self):
#         return self.title
# 
#     def get_absolute_url(self):
#         return getattr(settings, 'INVOICING_INVOICE_ITEM_ABSOLUTE_URL', lambda item: '')(self)
# 
#     @property
#     def subtotal(self):
#         subtotal = round(self.unit_price * self.quantity, 2)
#         return round(Decimal(subtotal) * Decimal((100 - self.discount) / 100), 2)
# 
#     @property
#     def discount_amount(self):
#         subtotal = round(self.unit_price * self.quantity, 2)
#         return round(Decimal(subtotal) * Decimal(self.discount / 100), 2)
# 
#     @property
#     def vat(self):
#         return round(self.subtotal * Decimal(self.tax_rate)/100 if self.tax_rate else 0, 2)
# 
#     @property
#     def unit_price_with_vat(self):
#         tax_rate = self.tax_rate if self.tax_rate else 0
#         return round(Decimal(self.unit_price) * Decimal((100 + tax_rate) / 100), 2)
# 
#     @property
#     def total(self):
#         return round(self.subtotal + self.vat, 2)
# 
#     def save(self, **kwargs):
#         # If tax rate is not set while creating new invoice item, set it according billing details
#         if self.tax_rate in EMPTY_VALUES and self.pk is None:
#             self.tax_rate = self.invoice.get_tax_rate()
#         return super(Item, self).save(**kwargs)


# Path: invoicing/signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from invoicing.models import Item



@receiver(post_save, sender=Item)
@receiver(post_delete, sender=Item)
def recalculate(instance, **kwargs):
    invoice = instance.invoice
    invoice.total = invoice.calculate_total()

    invoice.vat = invoice.calculate_vat()