diff --git a/invoices/logos/sageteam-logo.png b/invoices/logos/sageteam-logo.png new file mode 100644 index 0000000..889e8a6 Binary files /dev/null and b/invoices/logos/sageteam-logo.png differ diff --git a/invoices/signatures/Digital_Sign_Sepehr_Akbarzadeh.png b/invoices/signatures/Digital_Sign_Sepehr_Akbarzadeh.png new file mode 100644 index 0000000..d8125e4 Binary files /dev/null and b/invoices/signatures/Digital_Sign_Sepehr_Akbarzadeh.png differ diff --git a/sage_invoice/admin/invoice.py b/sage_invoice/admin/invoice.py index faa9fc4..841d4ec 100644 --- a/sage_invoice/admin/invoice.py +++ b/sage_invoice/admin/invoice.py @@ -14,7 +14,7 @@ class ItemInline(admin.TabularInline): readonly_fields = ("total_price",) -class ColumnInline(admin.TabularInline): +class ColumnInline(admin.StackedInline): model = Column extra = 1 diff --git a/sage_invoice/migrations/0003_alter_item_quantity.py b/sage_invoice/migrations/0003_alter_item_quantity.py new file mode 100644 index 0000000..4057c5c --- /dev/null +++ b/sage_invoice/migrations/0003_alter_item_quantity.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.2 on 2024-10-17 11:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("sage_invoice", "0002_alter_invoice_template_choice"), + ] + + operations = [ + migrations.AlterField( + model_name="item", + name="quantity", + field=models.PositiveIntegerField( + blank=True, + db_comment="The quantity of the invoice item", + help_text="The quantity of the item.", + null=True, + verbose_name="Quantity", + ), + ), + ] diff --git a/sage_invoice/migrations/0004_alter_expense_invoice.py b/sage_invoice/migrations/0004_alter_expense_invoice.py new file mode 100644 index 0000000..6c949b0 --- /dev/null +++ b/sage_invoice/migrations/0004_alter_expense_invoice.py @@ -0,0 +1,26 @@ +# Generated by Django 5.1.2 on 2024-10-17 13:00 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("sage_invoice", "0003_alter_item_quantity"), + ] + + operations = [ + migrations.AlterField( + model_name="expense", + name="invoice", + field=models.OneToOneField( + db_comment="Reference to the associated invoice", + help_text="The invoice associated with this total.", + on_delete=django.db.models.deletion.CASCADE, + related_name="expense", + to="sage_invoice.invoice", + verbose_name="Invoice", + ), + ), + ] diff --git a/sage_invoice/models/expense.py b/sage_invoice/models/expense.py index d23c63b..c1fde75 100644 --- a/sage_invoice/models/expense.py +++ b/sage_invoice/models/expense.py @@ -73,7 +73,7 @@ class Expense(models.Model): "Invoice", verbose_name=_("Invoice"), on_delete=models.CASCADE, - related_name="total", + related_name="expense", help_text=_("The invoice associated with this total."), db_comment="Reference to the associated invoice", ) diff --git a/sage_invoice/models/item.py b/sage_invoice/models/item.py index bf53624..4535e23 100644 --- a/sage_invoice/models/item.py +++ b/sage_invoice/models/item.py @@ -11,7 +11,8 @@ class Item(models.Model): ) quantity = models.PositiveIntegerField( verbose_name=_("Quantity"), - default=1, + null=True, + blank=True, help_text=_("The quantity of the item."), db_comment="The quantity of the invoice item", ) @@ -49,7 +50,10 @@ class Item(models.Model): ) def save(self, *args, **kwargs): - self.total_price = self.quantity * self.unit_price + if self.quantity: + self.total_price = self.quantity * self.unit_price + else: + self.total_price = self.unit_price super().save(*args, **kwargs) def __str__(self): diff --git a/sage_invoice/templates/quotation_4.html b/sage_invoice/templates/quotation_4.html index ee44fab..45159c0 100644 --- a/sage_invoice/templates/quotation_4.html +++ b/sage_invoice/templates/quotation_4.html @@ -1,16 +1,16 @@ -{% load static custom_filters %} +{% load static custom_filters humanize i18n %}
-Invoice No: {{ tracking_code }}
-Date: {{ invoice_date }}
++ {% trans "Invoice No: " %} + {{ invoice.tracking_code }} +
++ {% trans "Date: " %} + {{ invoice.invoice_date }} +
Invoice To:
++ + {% trans "Invoice To:" %} + +
- {{ customer_name }}
- {{ customer_email }}
- {{ customer_phone }}
+ {{ invoice.customer_name }}
+ {% if customer_email %}
+ {{ customer_email|default:'' }}
+ {% else %}
+ {{ customer_phone|default:'' }}
+ {% endif %}
Pay To:
-
- Your Company Name
- Company Address
-
Item | -Description | - {% for column in custom_columns %} -{{ column }} | +{% trans "Item" %} | +{% trans "Description" %} | ++ {% trans "Qty" %} + | + {% for column in invoice.columns.all %} ++ {{ column }} + | {% endfor %} -Price | -Qty | -Total | ++ {% trans "Price" %} + | + ++ {% trans "Total" %} + |
---|---|---|---|---|---|---|---|---|---|---|---|
{{ forloop.counter }}. | {{ item.description }} | - {% for column in custom_columns %} -{{ item.custom_data|get_item:column }} | ++ {% if item.quantity %} + {{ item.quantity }} + {% else %} + - + {% endif %} + {{ item.measurement|default:'' }} + | + {% for column in invoice.columns.all %} ++ {% if column.item == item %} + {{ column.value }} + {% else %} + - + {% endif %} + | {% endfor %} -{{ item.unit_price }} {{ currency }} | -{{ item.quantity }} {{ item.measurement }} | -{{ item.total_price }} {{ currency }} | - ++ {{ item.unit_price|intcomma }} {{ invoice.currency }} + | ++ {{ item.total_price|intcomma }} {{ invoice.currency }} + |