Add the invoice template

This commit is contained in:
amalelshihaby 2021-08-04 12:03:55 +02:00
commit 5bb0c4cdda
24 changed files with 461 additions and 95 deletions

View file

@ -0,0 +1,24 @@
# Generated by Django 3.2.4 on 2021-08-03 21:18
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0024_auto_20210730_1441'),
]
operations = [
migrations.AlterField(
model_name='billrecord',
name='bill',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bill_records', to='uncloud_pay.bill'),
),
migrations.AlterField(
model_name='payment',
name='type',
field=models.CharField(choices=[('withdraw', 'Withdraw Money'), ('deposit', 'Deposit Money')], default='deposit', max_length=256),
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 3.2.4 on 2021-08-03 21:40
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0025_auto_20210803_2118'),
]
operations = [
migrations.RemoveField(
model_name='order',
name='description',
),
]

View file

@ -649,8 +649,6 @@ class Order(models.Model):
customer = models.ForeignKey(StripeCustomer, on_delete=models.CASCADE, null=True)
description = models.TextField()
product = models.ForeignKey(Product, blank=False, null=False, on_delete=models.CASCADE)
config = models.JSONField()
@ -806,6 +804,19 @@ class Order(models.Model):
@property
def is_one_time(self):
return not self.is_recurring
@property
def description(self):
desc = self.product.description + "( "
config = json.loads(self.config)
if config and config["cores"]:
desc = f"{desc} {config['cores']} Cores,"
if config and config["memory"]:
desc = f"{desc} {config['memory']} RAM,"
if config and config["storage"]:
desc = f"{desc} {config['storage']} GB SSD,"
desc += " )"
return desc
def replace_with(self, new_order):
new_order.replaces = self
@ -1011,6 +1022,11 @@ class Bill(models.Model):
bill_records = BillRecord.objects.filter(bill=self)
return sum([ br.sum for br in bill_records ])
@property
def subtotal(self):
bill_records = BillRecord.objects.filter(bill=self)
return sum([ br.subtotal for br in bill_records ])
@property
def vat_rate(self):
return VATRate.get_vat_rate(self.billing_address, when=self.ending_date)
@ -1114,7 +1130,7 @@ class BillRecord(models.Model):
Entry of a bill, dynamically generated from an order.
"""
bill = models.ForeignKey(Bill, on_delete=models.CASCADE)
bill = models.ForeignKey(Bill, on_delete=models.CASCADE, related_name='bill_records')
order = models.ForeignKey(Order, on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
@ -1142,12 +1158,30 @@ class BillRecord(models.Model):
else:
return self.order.one_time_price
@property
def description(self):
if self.order:
return self.order.description
return ''
@property
def price(self):
if self.is_recurring_record:
return self.order.recurring_price
else:
return self.order.one_time_price
@property
def subtotal(self):
billing_address_ins = self.order.billing_address
vat_rate = VATRate.get_vat_rate(billing_address_ins)
vat_validation_status = "verified" if billing_address_ins.vat_number_validated_on and billing_address_ins.vat_number_verified else False
config = json.loads(self.order.config)
pricing = uncloud_pay.utils.get_order_total_with_vat(
config["cores"], config["memory"], config["storage"], self.order.pricing_plan.name,
vat_rate=vat_rate * 100, vat_validation_status = vat_validation_status
)
return pricing['subtotal_after_discount']
def __str__(self):
if self.is_recurring_record:

View file

@ -124,10 +124,11 @@ def apply_vat_discount(subtotal, pricing_plan, vat_rate=False, vat_validation_st
'amount_with_vat': round(float(discount_amount_with_vat), 2)
}
subtotal_after_discount = subtotal - discount["amount"]
vat_amount = round(vat_percent * 0.01 * subtotal_after_discount, 2)
price_after_discount_with_vat = round((subtotal - discount['amount']) * (1 + vat_percent * 0.01), 2)
return (subtotal, round(float(subtotal_after_discount), 2), price_after_discount_with_vat,
round(float(vat), 2), vat_percent, discount)
round(float(vat), 2), vat_percent, vat_amount, discount)
def get_order_total_with_vat(cores, memory, storage,
@ -149,13 +150,14 @@ def get_order_total_with_vat(cores, memory, storage,
(decimal.Decimal(memory) * pricing.ram_unit_price) +
(decimal.Decimal(storage) * (pricing.storage_unit_price))
)
subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, discount = \
subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, vat_amount, discount = \
apply_vat_discount(subtotal, pricing, vat_rate, vat_validation_status)
return {
"name": pricing.name,
"subtotal": subtotal,
"discount": discount,
"vat": vat, "vat_percent": vat_percent,
'vat_amount': vat_amount,
"vat_validation_status": vat_validation_status,
"subtotal_after_discount": subtotal_after_discount,
"total": price_after_discount_with_vat