diff --git a/accounting/__init__.py b/accounting/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/accounting/__pycache__/__init__.cpython-311.pyc b/accounting/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..fbc0960
Binary files /dev/null and b/accounting/__pycache__/__init__.cpython-311.pyc differ
diff --git a/accounting/__pycache__/admin.cpython-311.pyc b/accounting/__pycache__/admin.cpython-311.pyc
new file mode 100644
index 0000000..8b75e5d
Binary files /dev/null and b/accounting/__pycache__/admin.cpython-311.pyc differ
diff --git a/accounting/__pycache__/apps.cpython-311.pyc b/accounting/__pycache__/apps.cpython-311.pyc
new file mode 100644
index 0000000..2b3d714
Binary files /dev/null and b/accounting/__pycache__/apps.cpython-311.pyc differ
diff --git a/accounting/__pycache__/models.cpython-311.pyc b/accounting/__pycache__/models.cpython-311.pyc
new file mode 100644
index 0000000..f9cc293
Binary files /dev/null and b/accounting/__pycache__/models.cpython-311.pyc differ
diff --git a/accounting/__pycache__/urls.cpython-311.pyc b/accounting/__pycache__/urls.cpython-311.pyc
new file mode 100644
index 0000000..7944071
Binary files /dev/null and b/accounting/__pycache__/urls.cpython-311.pyc differ
diff --git a/accounting/__pycache__/views.cpython-311.pyc b/accounting/__pycache__/views.cpython-311.pyc
new file mode 100644
index 0000000..de20ae3
Binary files /dev/null and b/accounting/__pycache__/views.cpython-311.pyc differ
diff --git a/accounting/admin.py b/accounting/admin.py
new file mode 100644
index 0000000..76bfd18
--- /dev/null
+++ b/accounting/admin.py
@@ -0,0 +1,22 @@
+from django.contrib import admin
+from .models import Account, JournalEntry, Ledger, Invoice, InvoiceItem, Bill, BillItem
+
+class InvoiceItemInline(admin.TabularInline):
+ model = InvoiceItem
+ extra = 1
+
+class InvoiceAdmin(admin.ModelAdmin):
+ inlines = [InvoiceItemInline]
+
+class BillItemInline(admin.TabularInline):
+ model = BillItem
+ extra = 1
+
+class BillAdmin(admin.ModelAdmin):
+ inlines = [BillItemInline]
+
+admin.site.register(Account)
+admin.site.register(JournalEntry)
+admin.site.register(Ledger)
+admin.site.register(Invoice, InvoiceAdmin)
+admin.site.register(Bill, BillAdmin)
\ No newline at end of file
diff --git a/accounting/apps.py b/accounting/apps.py
new file mode 100644
index 0000000..cde39bc
--- /dev/null
+++ b/accounting/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AccountingConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'accounting'
diff --git a/accounting/migrations/0001_initial.py b/accounting/migrations/0001_initial.py
new file mode 100644
index 0000000..1602ebf
--- /dev/null
+++ b/accounting/migrations/0001_initial.py
@@ -0,0 +1,24 @@
+# Generated by Django 5.2.7 on 2025-12-16 14:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Account',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100)),
+ ('number', models.CharField(max_length=20, unique=True)),
+ ('type', models.CharField(choices=[('ASSET', 'Asset'), ('LIABILITY', 'Liability'), ('EQUITY', 'Equity'), ('REVENUE', 'Revenue'), ('EXPENSE', 'Expense')], max_length=10)),
+ ('balance', models.DecimalField(decimal_places=2, default=0.0, max_digits=15)),
+ ],
+ ),
+ ]
diff --git a/accounting/migrations/0002_journalentry_ledger.py b/accounting/migrations/0002_journalentry_ledger.py
new file mode 100644
index 0000000..6f64077
--- /dev/null
+++ b/accounting/migrations/0002_journalentry_ledger.py
@@ -0,0 +1,32 @@
+# Generated by Django 5.2.7 on 2025-12-16 14:14
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounting', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='JournalEntry',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('date', models.DateField()),
+ ('description', models.CharField(max_length=255)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Ledger',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('debit', models.DecimalField(decimal_places=2, default=0.0, max_digits=15)),
+ ('credit', models.DecimalField(decimal_places=2, default=0.0, max_digits=15)),
+ ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounting.account')),
+ ('journal_entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounting.journalentry')),
+ ],
+ ),
+ ]
diff --git a/accounting/migrations/0003_invoice_invoiceitem.py b/accounting/migrations/0003_invoice_invoiceitem.py
new file mode 100644
index 0000000..581e41e
--- /dev/null
+++ b/accounting/migrations/0003_invoice_invoiceitem.py
@@ -0,0 +1,36 @@
+# Generated by Django 5.2.7 on 2025-12-16 14:16
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounting', '0002_journalentry_ledger'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Invoice',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('customer_name', models.CharField(max_length=255)),
+ ('invoice_date', models.DateField()),
+ ('due_date', models.DateField()),
+ ('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=15)),
+ ('paid', models.BooleanField(default=False)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='InvoiceItem',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('description', models.CharField(max_length=255)),
+ ('quantity', models.PositiveIntegerField(default=1)),
+ ('unit_price', models.DecimalField(decimal_places=2, max_digits=15)),
+ ('total', models.DecimalField(decimal_places=2, max_digits=15)),
+ ('invoice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='accounting.invoice')),
+ ],
+ ),
+ ]
diff --git a/accounting/migrations/0004_bill_billitem.py b/accounting/migrations/0004_bill_billitem.py
new file mode 100644
index 0000000..ef1b515
--- /dev/null
+++ b/accounting/migrations/0004_bill_billitem.py
@@ -0,0 +1,36 @@
+# Generated by Django 5.2.7 on 2025-12-16 14:18
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounting', '0003_invoice_invoiceitem'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Bill',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('vendor_name', models.CharField(max_length=255)),
+ ('bill_date', models.DateField()),
+ ('due_date', models.DateField()),
+ ('total_amount', models.DecimalField(decimal_places=2, default=0.0, max_digits=15)),
+ ('paid', models.BooleanField(default=False)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BillItem',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('description', models.CharField(max_length=255)),
+ ('quantity', models.PositiveIntegerField(default=1)),
+ ('unit_price', models.DecimalField(decimal_places=2, max_digits=15)),
+ ('total', models.DecimalField(decimal_places=2, max_digits=15)),
+ ('bill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='accounting.bill')),
+ ],
+ ),
+ ]
diff --git a/accounting/migrations/__init__.py b/accounting/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/accounting/migrations/__pycache__/0001_initial.cpython-311.pyc b/accounting/migrations/__pycache__/0001_initial.cpython-311.pyc
new file mode 100644
index 0000000..48bd4a5
Binary files /dev/null and b/accounting/migrations/__pycache__/0001_initial.cpython-311.pyc differ
diff --git a/accounting/migrations/__pycache__/0002_journalentry_ledger.cpython-311.pyc b/accounting/migrations/__pycache__/0002_journalentry_ledger.cpython-311.pyc
new file mode 100644
index 0000000..23b3635
Binary files /dev/null and b/accounting/migrations/__pycache__/0002_journalentry_ledger.cpython-311.pyc differ
diff --git a/accounting/migrations/__pycache__/0003_invoice_invoiceitem.cpython-311.pyc b/accounting/migrations/__pycache__/0003_invoice_invoiceitem.cpython-311.pyc
new file mode 100644
index 0000000..90205cd
Binary files /dev/null and b/accounting/migrations/__pycache__/0003_invoice_invoiceitem.cpython-311.pyc differ
diff --git a/accounting/migrations/__pycache__/0004_bill_billitem.cpython-311.pyc b/accounting/migrations/__pycache__/0004_bill_billitem.cpython-311.pyc
new file mode 100644
index 0000000..b3d29ac
Binary files /dev/null and b/accounting/migrations/__pycache__/0004_bill_billitem.cpython-311.pyc differ
diff --git a/accounting/migrations/__pycache__/__init__.cpython-311.pyc b/accounting/migrations/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..2be6429
Binary files /dev/null and b/accounting/migrations/__pycache__/__init__.cpython-311.pyc differ
diff --git a/accounting/models.py b/accounting/models.py
new file mode 100644
index 0000000..f324c60
--- /dev/null
+++ b/accounting/models.py
@@ -0,0 +1,74 @@
+from django.db import models
+
+class Account(models.Model):
+ ACCOUNT_TYPE_CHOICES = (
+ ('ASSET', 'Asset'),
+ ('LIABILITY', 'Liability'),
+ ('EQUITY', 'Equity'),
+ ('REVENUE', 'Revenue'),
+ ('EXPENSE', 'Expense'),
+ )
+
+ name = models.CharField(max_length=100)
+ number = models.CharField(max_length=20, unique=True)
+ type = models.CharField(max_length=10, choices=ACCOUNT_TYPE_CHOICES)
+ balance = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
+
+ def __str__(self):
+ return f'{self.number} - {self.name}'
+
+class JournalEntry(models.Model):
+ date = models.DateField()
+ description = models.CharField(max_length=255)
+
+ def __str__(self):
+ return f'{self.date} - {self.description}'
+
+class Ledger(models.Model):
+ journal_entry = models.ForeignKey(JournalEntry, on_delete=models.CASCADE)
+ account = models.ForeignKey(Account, on_delete=models.CASCADE)
+ debit = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
+ credit = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
+
+ def __str__(self):
+ return f'{self.journal_entry} - {self.account}'
+
+class Invoice(models.Model):
+ customer_name = models.CharField(max_length=255)
+ invoice_date = models.DateField()
+ due_date = models.DateField()
+ total_amount = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
+ paid = models.BooleanField(default=False)
+
+ def __str__(self):
+ return f'Invoice #{self.id} - {self.customer_name}'
+
+class InvoiceItem(models.Model):
+ invoice = models.ForeignKey(Invoice, related_name='items', on_delete=models.CASCADE)
+ description = models.CharField(max_length=255)
+ quantity = models.PositiveIntegerField(default=1)
+ unit_price = models.DecimalField(max_digits=15, decimal_places=2)
+ total = models.DecimalField(max_digits=15, decimal_places=2)
+
+ def __str__(self):
+ return f'{self.description} ({self.quantity} @ {self.unit_price})'
+
+class Bill(models.Model):
+ vendor_name = models.CharField(max_length=255)
+ bill_date = models.DateField()
+ due_date = models.DateField()
+ total_amount = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
+ paid = models.BooleanField(default=False)
+
+ def __str__(self):
+ return f'Bill #{self.id} - {self.vendor_name}'
+
+class BillItem(models.Model):
+ bill = models.ForeignKey(Bill, related_name='items', on_delete=models.CASCADE)
+ description = models.CharField(max_length=255)
+ quantity = models.PositiveIntegerField(default=1)
+ unit_price = models.DecimalField(max_digits=15, decimal_places=2)
+ total = models.DecimalField(max_digits=15, decimal_places=2)
+
+ def __str__(self):
+ return f'{self.description} ({self.quantity} @ {self.unit_price})'
\ No newline at end of file
diff --git a/accounting/templates/accounting/account_list.html b/accounting/templates/accounting/account_list.html
new file mode 100644
index 0000000..979eb70
--- /dev/null
+++ b/accounting/templates/accounting/account_list.html
@@ -0,0 +1,25 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
Chart of Accounts
+
+
+
+ | Number |
+ Name |
+ Type |
+ Balance |
+
+
+
+ {% for account in accounts %}
+
+ | {{ account.number }} |
+ {{ account.name }} |
+ {{ account.get_type_display }} |
+ {{ account.balance }} |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/accounting/templates/accounting/bill_list.html b/accounting/templates/accounting/bill_list.html
new file mode 100644
index 0000000..6c0ddb2
--- /dev/null
+++ b/accounting/templates/accounting/bill_list.html
@@ -0,0 +1,31 @@
+{% extends 'base.html' %}
+
+{% block title %}Bills{% endblock %}
+
+{% block content %}
+ Bills
+
+
+
+ | Bill # |
+ Vendor |
+ Bill Date |
+ Due Date |
+ Total |
+ Paid |
+
+
+
+ {% for bill in bills %}
+
+ | {{ bill.id }} |
+ {{ bill.vendor_name }} |
+ {{ bill.bill_date }} |
+ {{ bill.due_date }} |
+ {{ bill.total_amount }} |
+ {{ bill.paid|yesno:"Yes,No" }} |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/accounting/templates/accounting/invoice_list.html b/accounting/templates/accounting/invoice_list.html
new file mode 100644
index 0000000..edc0b46
--- /dev/null
+++ b/accounting/templates/accounting/invoice_list.html
@@ -0,0 +1,29 @@
+{% extends 'base.html' %}
+
+{% block content %}
+ Invoices
+
+
+
+ | Invoice # |
+ Customer |
+ Date |
+ Due Date |
+ Total |
+ Paid |
+
+
+
+ {% for invoice in invoices %}
+
+ | {{ invoice.id }} |
+ {{ invoice.customer_name }} |
+ {{ invoice.invoice_date }} |
+ {{ invoice.due_date }} |
+ ${{ invoice.total_amount }} |
+ {{ invoice.paid|yesno:"Yes,No" }} |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/accounting/templates/accounting/trial_balance.html b/accounting/templates/accounting/trial_balance.html
new file mode 100644
index 0000000..510c12e
--- /dev/null
+++ b/accounting/templates/accounting/trial_balance.html
@@ -0,0 +1,32 @@
+{% extends 'base.html' %}
+
+{% block content %}
+ Trial Balance
+
+
+
+ | Account Number |
+ Account Name |
+ Debit |
+ Credit |
+
+
+
+ {% for item in report_data %}
+
+ | {{ item.number }} |
+ {{ item.name }} |
+ {{ item.debit }} |
+ {{ item.credit }} |
+
+ {% endfor %}
+
+
+
+ | Total |
+ {{ total_debits }} |
+ {{ total_credits }} |
+
+
+
+{% endblock %}
diff --git a/accounting/tests.py b/accounting/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/accounting/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/accounting/urls.py b/accounting/urls.py
new file mode 100644
index 0000000..55fb769
--- /dev/null
+++ b/accounting/urls.py
@@ -0,0 +1,11 @@
+from django.urls import path
+from . import views
+
+app_name = 'accounting'
+
+urlpatterns = [
+ path('accounts/', views.account_list, name='account_list'),
+ path('trial-balance/', views.trial_balance, name='trial_balance'),
+ path('invoices/', views.invoice_list, name='invoice_list'),
+ path('bills/', views.bill_list, name='bill_list'),
+]
diff --git a/accounting/views.py b/accounting/views.py
new file mode 100644
index 0000000..98fe096
--- /dev/null
+++ b/accounting/views.py
@@ -0,0 +1,43 @@
+from django.shortcuts import render
+from .models import Account, Ledger, Invoice, Bill
+from django.db.models import Sum
+
+def account_list(request):
+ accounts = Account.objects.all()
+ return render(request, 'accounting/account_list.html', {'accounts': accounts})
+
+def trial_balance(request):
+ accounts = Account.objects.all()
+ report_data = []
+ total_debits = 0
+ total_credits = 0
+
+ for account in accounts:
+ debit_total = Ledger.objects.filter(account=account).aggregate(Sum('debit'))['debit__sum'] or 0
+ credit_total = Ledger.objects.filter(account=account).aggregate(Sum('credit'))['credit__sum'] or 0
+
+ balance = debit_total - credit_total
+
+ report_data.append({
+ 'number': account.number,
+ 'name': account.name,
+ 'debit': debit_total,
+ 'credit': credit_total,
+ })
+
+ total_debits += debit_total
+ total_credits += credit_total
+
+ return render(request, 'accounting/trial_balance.html', {
+ 'report_data': report_data,
+ 'total_debits': total_debits,
+ 'total_credits': total_credits,
+ })
+
+def invoice_list(request):
+ invoices = Invoice.objects.all()
+ return render(request, 'accounting/invoice_list.html', {'invoices': invoices})
+
+def bill_list(request):
+ bills = Bill.objects.all()
+ return render(request, 'accounting/bill_list.html', {'bills': bills})
\ No newline at end of file
diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc
index 5be02db..4b1f668 100644
Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ
diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc
index 28817aa..90a9a88 100644
Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ
diff --git a/config/settings.py b/config/settings.py
index 291d043..4ffdb6b 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -56,6 +56,7 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'core',
+ 'accounting',
]
MIDDLEWARE = [
diff --git a/config/urls.py b/config/urls.py
index bcfc074..dfc2017 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -22,6 +22,7 @@ from django.conf.urls.static import static
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("core.urls")),
+ path("accounting/", include("accounting.urls")),
]
if settings.DEBUG:
diff --git a/core/templates/base.html b/core/templates/base.html
index 1e7e5fb..425d898 100644
--- a/core/templates/base.html
+++ b/core/templates/base.html
@@ -3,7 +3,8 @@
- {% block title %}Knowledge Base{% endblock %}
+
+ {% block title %}Smart Accounting{% endblock %}
{% if project_description %}
@@ -13,13 +14,52 @@
{% endif %}
+
+
+
+
+
+
{% load static %}
+
{% block head %}{% endblock %}
- {% block content %}{% endblock %}
+
+
+
+ {% block content %}{% endblock %}
+
+
+
+
+