Add the invoice template
This commit is contained in:
parent
030a0cd501
commit
5bb0c4cdda
24 changed files with 461 additions and 95 deletions
24
uncloud_pay/migrations/0025_auto_20210803_2118.py
Normal file
24
uncloud_pay/migrations/0025_auto_20210803_2118.py
Normal 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),
|
||||
),
|
||||
]
|
||||
17
uncloud_pay/migrations/0026_remove_order_description.py
Normal file
17
uncloud_pay/migrations/0026_remove_order_description.py
Normal 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',
|
||||
),
|
||||
]
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue