add ledger and journalentry
This commit is contained in:
parent
55167f2cc1
commit
68fb46cf65
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,8 +5,7 @@ class InventoryConfig(AppConfig):
|
|||||||
name = 'inventory'
|
name = 'inventory'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
import inventory.signals
|
import inventory.signals
|
||||||
# from decimal import Decimal
|
from decimal import Decimal
|
||||||
# from inventory.models import VatRate
|
from inventory.models import VatRate
|
||||||
# VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)
|
VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,9 @@ from django_ledger.forms.estimate import (
|
|||||||
EstimateModelCreateForm as EstimateModelCreateFormBase,
|
EstimateModelCreateForm as EstimateModelCreateFormBase,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# from django_ledger.forms.ledger import LedgerModelCreateForm as LedgerModelCreateFormBase
|
||||||
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
|
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
|
||||||
|
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Dealer,
|
Dealer,
|
||||||
@ -953,3 +955,10 @@ class DealersMakeForm(forms.Form):
|
|||||||
|
|
||||||
for car_make in self.cleaned_data["car_makes"]:
|
for car_make in self.cleaned_data["car_makes"]:
|
||||||
DealersMake.objects.create(dealer=self.dealer, car_make=car_make)
|
DealersMake.objects.create(dealer=self.dealer, car_make=car_make)
|
||||||
|
|
||||||
|
|
||||||
|
class JournalEntryModelCreateForm(JournalEntryModelCreateFormBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# class LedgerModelCreateForm(LedgerModelCreateFormBase):
|
||||||
|
# pass
|
||||||
@ -82,11 +82,6 @@ def create_car_location(sender, instance, created, **kwargs):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to create CarLocation for car {instance.vin}: {e}")
|
print(f"Failed to create CarLocation for car {instance.vin}: {e}")
|
||||||
|
|
||||||
@receiver(post_save, sender=models.Dealer)
|
|
||||||
def create_dealer_settings(sender, instance, created, **kwargs):
|
|
||||||
if created:
|
|
||||||
models.DealerSettings.objects.create(dealer=instance)
|
|
||||||
|
|
||||||
# Create Entity
|
# Create Entity
|
||||||
@receiver(post_save, sender=models.Dealer)
|
@receiver(post_save, sender=models.Dealer)
|
||||||
def create_ledger_entity(sender, instance, created, **kwargs):
|
def create_ledger_entity(sender, instance, created, **kwargs):
|
||||||
@ -624,8 +619,7 @@ def create_ledger_entity(sender, instance, created, **kwargs):
|
|||||||
entity.create_account(coa_model=coa, code="6302", role=roles.EXPENSE_OTHER, name=_("Taxes"), balance_type="debit", active=True)
|
entity.create_account(coa_model=coa, code="6302", role=roles.EXPENSE_OTHER, name=_("Taxes"), balance_type="debit", active=True)
|
||||||
entity.create_account(coa_model=coa, code="6303", role=roles.EXPENSE_OTHER, name=_("Foreign Currency Translation"), balance_type="debit", active=True)
|
entity.create_account(coa_model=coa, code="6303", role=roles.EXPENSE_OTHER, name=_("Foreign Currency Translation"), balance_type="debit", active=True)
|
||||||
entity.create_account(coa_model=coa, code="6304", role=roles.EXPENSE_OTHER, name=_("Interest Expenses"), balance_type="debit", active=True)
|
entity.create_account(coa_model=coa, code="6304", role=roles.EXPENSE_OTHER, name=_("Interest Expenses"), balance_type="debit", active=True)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=models.Dealer)
|
@receiver(post_save, sender=models.Dealer)
|
||||||
def create_dealer_groups(sender, instance, created, **kwargs):
|
def create_dealer_groups(sender, instance, created, **kwargs):
|
||||||
|
|
||||||
@ -872,6 +866,24 @@ def update_car_status_on_reservation_update(sender, instance, **kwargs):
|
|||||||
car.status = models.CarStatusChoices.AVAILABLE
|
car.status = models.CarStatusChoices.AVAILABLE
|
||||||
car.save()
|
car.save()
|
||||||
|
|
||||||
|
@receiver(post_save, sender=models.Dealer)
|
||||||
|
def create_dealer_settings(sender, instance, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
models.DealerSettings.objects.create(
|
||||||
|
dealer=instance,
|
||||||
|
invoice_cash_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH).first(),
|
||||||
|
invoice_prepaid_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).first(),
|
||||||
|
invoice_unearned_account=instance.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_DEFERRED_REVENUE).first(),
|
||||||
|
bill_cash_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH).first(),
|
||||||
|
bill_prepaid_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_PREPAID).first(),
|
||||||
|
bill_unearned_account=instance.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).first()
|
||||||
|
)
|
||||||
|
|
||||||
|
@receiver(post_save, sender=models.Dealer)
|
||||||
|
def check_if_vat_exists(sender, instance, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
models.VatRate.objects.get_create(is_active=True)
|
||||||
|
|
||||||
# @receiver(post_save, sender=EstimateModel)
|
# @receiver(post_save, sender=EstimateModel)
|
||||||
# def update_estimate_status(sender, instance,created, **kwargs):
|
# def update_estimate_status(sender, instance,created, **kwargs):
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ from django import template
|
|||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.formats import number_format
|
from django.utils.formats import number_format
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
# from django_ledger import __version__
|
# from django_ledger import __version__
|
||||||
# from django_ledger.forms.app_filters import EntityFilterForm, ActivityFilterForm
|
# from django_ledger.forms.app_filters import EntityFilterForm, ActivityFilterForm
|
||||||
@ -27,7 +28,9 @@ from django_ledger.io.io_core import validate_activity, get_localdate
|
|||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.filter()
|
||||||
|
def to_int(value):
|
||||||
|
return Decimal(value).quantize(Decimal("0.01"))
|
||||||
# @register.simple_tag(name='current_version')
|
# @register.simple_tag(name='current_version')
|
||||||
# def current_version():
|
# def current_version():
|
||||||
# return __version__
|
# return __version__
|
||||||
|
|||||||
@ -407,6 +407,33 @@ urlpatterns = [
|
|||||||
name="representative_delete",
|
name="representative_delete",
|
||||||
),
|
),
|
||||||
# Ledger URLS
|
# Ledger URLS
|
||||||
|
# Ledger
|
||||||
|
path(
|
||||||
|
"ledgers/", views.LedgerModelListView.as_view(), name="ledger_list"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"ledgers/<slug:entity_slug>/detail/<uuid:invoice_pk>/", views.LedgerModelDetailView.as_view(), name="ledger_detail"
|
||||||
|
),
|
||||||
|
# path(
|
||||||
|
# "ledgers/create/", views.LedgerModelCreateView.as_view(), name="ledger_create"
|
||||||
|
# ),
|
||||||
|
path(
|
||||||
|
"journalentries/<uuid:pk>/list/", views.JournalEntryListView.as_view(), name="journalentry_list"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"journalentries/<uuid:pk>/create/", views.JournalEntryCreateView.as_view(), name="journalentry_create"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"journalentries/<uuid:pk>/delete/", views.JournalEntryDeleteView, name="journalentry_delete"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"journalentries/<uuid:pk>/transactions/",
|
||||||
|
views.JournalEntryTransactionsView,
|
||||||
|
name="journalentry_transactions",
|
||||||
|
),
|
||||||
|
path('journalentries/<slug:entity_slug>/<uuid:ledger_pk>/detail/<uuid:je_pk>/txs/',
|
||||||
|
views.JournalEntryModelTXSDetailView.as_view(),
|
||||||
|
name='journalentry_txs'),
|
||||||
# Bank Account
|
# Bank Account
|
||||||
path(
|
path(
|
||||||
"bank_accounts/", views.BankAccountListView.as_view(), name="bank_account_list"
|
"bank_accounts/", views.BankAccountListView.as_view(), name="bank_account_list"
|
||||||
@ -597,6 +624,7 @@ urlpatterns = [
|
|||||||
name="bill_mark_as_paid",
|
name="bill_mark_as_paid",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
# orders
|
# orders
|
||||||
path("orders/", views.OrderListView.as_view(), name="order_list_view"),
|
path("orders/", views.OrderListView.as_view(), name="order_list_view"),
|
||||||
|
|
||||||
|
|||||||
@ -48,12 +48,15 @@ from django.views.generic import (
|
|||||||
UpdateView,
|
UpdateView,
|
||||||
DeleteView,
|
DeleteView,
|
||||||
TemplateView,
|
TemplateView,
|
||||||
|
ArchiveIndexView,
|
||||||
)
|
)
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
# Django Ledger
|
# Django Ledger
|
||||||
from django_ledger.io import roles
|
from django_ledger.io import roles
|
||||||
from django_ledger.utils import accruable_net_summary
|
from django_ledger.utils import accruable_net_summary
|
||||||
|
from django_ledger.views.invoice import InvoiceModelDetailView as InvoiceModelDetailViewBase
|
||||||
|
from django_ledger.views import LedgerModelListView as LedgerModelListViewBase,JournalEntryModelTXSDetailView as JournalEntryModelTXSDetailViewBase
|
||||||
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
|
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
|
||||||
from django_ledger.views.entity import EntityModelDetailBaseView,EntityModelDetailHandlerView
|
from django_ledger.views.entity import EntityModelDetailBaseView,EntityModelDetailHandlerView
|
||||||
from django_ledger.forms.item import (
|
from django_ledger.forms.item import (
|
||||||
@ -85,6 +88,7 @@ from django_ledger.models import (
|
|||||||
CustomerModel,
|
CustomerModel,
|
||||||
ItemModel,
|
ItemModel,
|
||||||
BillModel,
|
BillModel,
|
||||||
|
LedgerModel,
|
||||||
VendorModel,
|
VendorModel,
|
||||||
)
|
)
|
||||||
from django_ledger.views.financial_statement import (
|
from django_ledger.views.financial_statement import (
|
||||||
@ -214,7 +218,7 @@ def dealer_signup(request, *args, **kwargs):
|
|||||||
user.groups.add(group)
|
user.groups.add(group)
|
||||||
for perm in Permission.objects.filter(content_type__app_label__in=["inventory","django_ledger"]):
|
for perm in Permission.objects.filter(content_type__app_label__in=["inventory","django_ledger"]):
|
||||||
group.permissions.add(perm)
|
group.permissions.add(perm)
|
||||||
|
|
||||||
StaffMember.objects.create(user=user)
|
StaffMember.objects.create(user=user)
|
||||||
models.Dealer.objects.create(
|
models.Dealer.objects.create(
|
||||||
user=user,
|
user=user,
|
||||||
@ -2569,6 +2573,8 @@ def invoice_create(request, pk):
|
|||||||
invoice.save()
|
invoice.save()
|
||||||
messages.success(request, "Invoice created successfully!")
|
messages.success(request, "Invoice created successfully!")
|
||||||
return redirect("invoice_detail", pk=invoice.pk)
|
return redirect("invoice_detail", pk=invoice.pk)
|
||||||
|
else:
|
||||||
|
print(form.errors)
|
||||||
form = forms.InvoiceModelCreateForm(
|
form = forms.InvoiceModelCreateForm(
|
||||||
entity_slug=entity.slug, user_model=entity.admin
|
entity_slug=entity.slug, user_model=entity.admin
|
||||||
)
|
)
|
||||||
@ -3993,7 +3999,7 @@ class CarListViewTable(LoginRequiredMixin, ExportMixin, SingleTableView):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def DealerSettingsView(request,pk):
|
def DealerSettingsView(request,pk):
|
||||||
dealer_setting = get_object_or_404(models.DealerSettings, pk=pk)
|
dealer_setting = get_object_or_404(models.DealerSettings, dealer__pk=pk)
|
||||||
dealer = get_user_type(request)
|
dealer = get_user_type(request)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = forms.DealerSettingsForm(request.POST, instance=dealer_setting)
|
form = forms.DealerSettingsForm(request.POST, instance=dealer_setting)
|
||||||
@ -4038,4 +4044,122 @@ def assign_car_makes(request):
|
|||||||
existing_car_makes = models.DealersMake.objects.filter(dealer=dealer).values_list("car_make", flat=True)
|
existing_car_makes = models.DealersMake.objects.filter(dealer=dealer).values_list("car_make", flat=True)
|
||||||
form = forms.DealersMakeForm(initial={"car_makes": existing_car_makes}, dealer=dealer)
|
form = forms.DealersMakeForm(initial={"car_makes": existing_car_makes}, dealer=dealer)
|
||||||
|
|
||||||
return render(request, "dealers/assign_car_makes.html", {"form": form})
|
return render(request, "dealers/assign_car_makes.html", {"form": form})
|
||||||
|
|
||||||
|
|
||||||
|
class LedgerModelListView(LoginRequiredMixin, ListView,ArchiveIndexView):
|
||||||
|
model = LedgerModel
|
||||||
|
context_object_name = "ledgers"
|
||||||
|
template_name = "ledger/ledger/ledger_list.html"
|
||||||
|
date_field = 'created'
|
||||||
|
ordering = '-created'
|
||||||
|
show_all = False
|
||||||
|
show_current = False
|
||||||
|
show_visible = False
|
||||||
|
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = super().get_queryset()
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
|
qs = qs.filter(entity=dealer.entity)
|
||||||
|
qs = qs.select_related('billmodel', 'invoicemodel')
|
||||||
|
qs = qs.order_by('-created')
|
||||||
|
if self.show_all:
|
||||||
|
return qs
|
||||||
|
if self.show_current:
|
||||||
|
qs = qs.current()
|
||||||
|
if self.show_visible:
|
||||||
|
qs = qs.visible()
|
||||||
|
return qs
|
||||||
|
|
||||||
|
class LedgerModelDetailView(InvoiceModelDetailViewBase):
|
||||||
|
model = LedgerModel
|
||||||
|
context_object_name = "ledger"
|
||||||
|
template_name = "ledger/ledger/ledger_detail.html"
|
||||||
|
|
||||||
|
# class LedgerModelCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView):
|
||||||
|
# model = LedgerModel
|
||||||
|
# template_name = "ledger/ledger/ledger_form.html"
|
||||||
|
# form_class = forms.LedgerModelCreateForm
|
||||||
|
# success_message = "Ledger created"
|
||||||
|
|
||||||
|
# def get_form(self, form_class=None):
|
||||||
|
# dealer = get_user_type(self.request)
|
||||||
|
# form = forms.LedgerModelCreateForm(entity_slug=dealer.entity.slug,user_model=dealer.entity.admin,**self.get_form_kwargs())
|
||||||
|
# return form
|
||||||
|
# def get_success_url(self):
|
||||||
|
# return reverse('ledger_list')
|
||||||
|
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# instance = form.save(commit=False)
|
||||||
|
# dealer = get_user_type(self.request)
|
||||||
|
# instance.entity = dealer.entity
|
||||||
|
# instance.save()
|
||||||
|
# return super().form_valid(form)
|
||||||
|
|
||||||
|
class JournalEntryListView(LoginRequiredMixin, ListView):
|
||||||
|
model = JournalEntryModel
|
||||||
|
context_object_name = "journal_entries"
|
||||||
|
template_name = "ledger/journal_entry/journal_entry_list.html"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = super().get_queryset()
|
||||||
|
ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first()
|
||||||
|
qs = qs.filter(ledger=ledger)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['ledger'] = LedgerModel.objects.filter(pk=self.kwargs['pk']).first()
|
||||||
|
return context
|
||||||
|
|
||||||
|
class JournalEntryCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView):
|
||||||
|
model = JournalEntryModel
|
||||||
|
template_name = "ledger/journal_entry/journal_entry_form.html"
|
||||||
|
form_class = forms.JournalEntryModelCreateForm
|
||||||
|
ledger_model = None
|
||||||
|
success_message = "Journal Entry created"
|
||||||
|
|
||||||
|
def get_form(self, form_class=None):
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
|
ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first()
|
||||||
|
form = forms.JournalEntryModelCreateForm(
|
||||||
|
entity_model=dealer.entity,
|
||||||
|
ledger_model=ledger,
|
||||||
|
**self.get_form_kwargs()
|
||||||
|
)
|
||||||
|
form.fields.pop('entity_unit')
|
||||||
|
return form
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["ledger"] = LedgerModel.objects.filter(pk=self.kwargs['pk']).first()
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first()
|
||||||
|
return reverse("journalentry_list", kwargs={"pk": ledger.pk})
|
||||||
|
|
||||||
|
|
||||||
|
def JournalEntryDeleteView(request,pk):
|
||||||
|
journal_entry = get_object_or_404(JournalEntryModel, pk=pk)
|
||||||
|
ledger = journal_entry.ledger
|
||||||
|
journal_entry.delete()
|
||||||
|
messages.success(request, 'Journal Entry deleted')
|
||||||
|
return redirect("journalentry_list", pk=ledger.pk)
|
||||||
|
|
||||||
|
def JournalEntryTransactionsView(request, pk):
|
||||||
|
journal = JournalEntryModel.objects.filter(pk=pk).first()
|
||||||
|
transactions = (
|
||||||
|
TransactionModel.objects.filter(journal_entry=journal)
|
||||||
|
.order_by("account__code")
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"ledger/journal_entry/journal_entry_transactions.html",
|
||||||
|
{"journal_entry": journal, "transactions": transactions},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class JournalEntryModelTXSDetailView(JournalEntryModelTXSDetailViewBase):
|
||||||
|
template_name = 'ledger/journal_entry/journal_entry_txs.html'
|
||||||
@ -249,6 +249,14 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.django_ledger.view_itemmodel %}
|
{% if perms.django_ledger.view_itemmodel %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'ledger_list' %}">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<span class="nav-link-icon"><span class="fas fa-book"></span></span><span class="nav-link-text">{% trans "Ledgers"|capfirst %}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'item_service_list' %}">
|
<a class="nav-link" href="{% url 'item_service_list' %}">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
@ -256,7 +264,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
|
||||||
{% if perms.django_ledger.view_itemmodel %}
|
{% if perms.django_ledger.view_itemmodel %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'item_expense_list' %}">
|
<a class="nav-link" href="{% url 'item_expense_list' %}">
|
||||||
@ -452,7 +459,6 @@
|
|||||||
<div class="card position-relative border-0">
|
<div class="card position-relative border-0">
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
<div class="text-center pt-4 pb-3">
|
<div class="text-center pt-4 pb-3">
|
||||||
|
|
||||||
<div class="avatar avatar-xl">
|
<div class="avatar avatar-xl">
|
||||||
{% if user.dealer.logo %}
|
{% if user.dealer.logo %}
|
||||||
<img class="rounded-circle" src="{{ user.dealer.logo.url }}" alt="" />
|
<img class="rounded-circle" src="{{ user.dealer.logo.url }}" alt="" />
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="d-flex flex-column min-vh-100">
|
<div class="d-flex flex-column min-vh-100">
|
||||||
<div class="d-flex flex-column flex-sm-grow-1 ms-sm-14 p-4">
|
<div class="d-flex flex-column flex-sm-grow-1 p-4">
|
||||||
<main class="d-grid gap-4 p-1">
|
<main class="d-grid gap-4 p-1">
|
||||||
<!-- Search Bar -->
|
<!-- Search Bar -->
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
|
|||||||
149
templates/ledger/journal_entry/includes/card_invoice.html
Normal file
149
templates/ledger/journal_entry/includes/card_invoice.html
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
{% load django_ledger %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% if not create_invoice %}
|
||||||
|
{% if style == 'dashboard' %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="text-muted text-end">
|
||||||
|
<span class="me-2">{% icon "bi:cash-stack" 16 %}</span>
|
||||||
|
{% trans 'Invoice' %}
|
||||||
|
</p>
|
||||||
|
<h3 class="card-title">{{ invoice.customer.customer_name }}</h3>
|
||||||
|
<p class="text-muted">{{ invoice.customer.address_1 }}</p>
|
||||||
|
{% if not invoice.is_past_due %}
|
||||||
|
<p class="h5 text-info">{% trans 'Due in' %}: {{ invoice.date_due | timeuntil }}</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-danger fw-bold h5">Past Due: {{ invoice.date_due | timesince }} ago</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if invoice.accrue %}
|
||||||
|
<p>Accrue: <span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span></p>
|
||||||
|
{% else %}
|
||||||
|
<p>Accrue: <span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span></p>
|
||||||
|
{% endif %}
|
||||||
|
<p class="h5 text-success">Owed to You: {% currency_symbol %}{{ invoice.get_amount_open | currency_format }}</p>
|
||||||
|
<p>Amount Paid: {% currency_symbol %}{{ invoice.amount_paid | currency_format }}</p>
|
||||||
|
<p>Progressed: {{ invoice.get_progress | percentage }}</p>
|
||||||
|
<div class="progress my-3">
|
||||||
|
<div class="progress-bar bg-success" role="progressbar" style="width: {{ invoice.get_progress_percent }}%" aria-valuenow="{{ invoice.get_progress_percent }}" aria-valuemin="0" aria-valuemax="100">{{ invoice.get_progress | percentage }}</div>
|
||||||
|
</div>
|
||||||
|
{% modal_action invoice 'get' entity_slug %}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex justify-content-between">
|
||||||
|
<a href="#" class="btn btn-link text-primary">{% trans 'View' %}</a>
|
||||||
|
<a href="#" class="btn btn-link text-warning">{% trans 'Update' %}</a>
|
||||||
|
{% if not invoice.is_paid %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_html_id }}')" class="btn btn-link text-info">{% trans 'Mark as Paid' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% elif style == 'invoice-detail' %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-title h3">
|
||||||
|
<span class="me-2">{% icon 'uil:bill' 36 %}</span>
|
||||||
|
{% trans 'Invoice Info' %}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
{% if invoice.is_draft %}
|
||||||
|
<h3 class="h3 text-warning fw-bold">{% trans 'This invoice is' %} {{ invoice.get_invoice_status_display }}</h3>
|
||||||
|
<p class="h3">{% trans 'Amount Due' %}: <span class="fw-bold">{% currency_symbol %}{{ invoice.amount_due | currency_format }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Due Date' %}: <span class="fw-bold">{{ invoice.date_due | timeuntil }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Is Accrued' %}:
|
||||||
|
{% if invoice.accrue %}
|
||||||
|
<span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% elif invoice.is_review %}
|
||||||
|
<h3 class="h3 text-warning fw-bold">{% trans 'This invoice is' %} {{ invoice.get_invoice_status_display }}</h3>
|
||||||
|
<p class="h3">{% trans 'Amount Due' %}: <span class="fw-bold">{% currency_symbol %}{{ invoice.amount_due | currency_format }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Due Date' %}: <span class="fw-bold">{{ invoice.date_due | timeuntil }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Is Accrued' %}:
|
||||||
|
{% if invoice.accrue %}
|
||||||
|
<span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% if invoice.xref %}
|
||||||
|
<p class="h5 fst-italic">{% trans 'External Ref' %}: {{ invoice.xref }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% elif invoice.is_approved %}
|
||||||
|
<h3 class="h3 text-info fw-bold">{% trans 'This invoice is' %} {{ invoice.get_invoice_status_display }}</h3>
|
||||||
|
<p class="h3">{% trans 'Amount Due' %}: <span class="fw-bold">{% currency_symbol %}{{ invoice.amount_due | currency_format }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Due Date' %}: <span class="fw-bold">{{ invoice.date_due | timeuntil }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Is Accrued' %}:
|
||||||
|
{% if invoice.accrue %}
|
||||||
|
<span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
<p class="h3 fw-bold">{% trans 'Amount Paid' %}: {% currency_symbol %}{{ invoice.amount_paid | currency_format }}</p>
|
||||||
|
<p class="h5">{% trans 'Progressed' %}: {{ invoice.get_progress | percentage }}</p>
|
||||||
|
<div class="progress my-3">
|
||||||
|
<div class="progress-bar bg-success" role="progressbar" style="width: {{ invoice.get_progress_percent }}%" aria-valuenow="{{ invoice.get_progress_percent }}" aria-valuemin="0" aria-valuemax="100">{{ invoice.get_progress | percentage }}</div>
|
||||||
|
</div>
|
||||||
|
{% elif invoice.is_paid %}
|
||||||
|
<h3 class="h3 text-success fw-bold">{% trans 'This invoice is' %} {{ invoice.get_invoice_status_display }}</h3>
|
||||||
|
<p class="h3">{% trans 'Amount Paid' %}: <span class="fw-bold">{% currency_symbol %}{{ invoice.amount_paid | currency_format }}</span></p>
|
||||||
|
<p class="h3">{% trans 'Paid Date' %}: <span class="fw-bold">{{ invoice.date_paid | date }}</span></p>
|
||||||
|
{% else %}
|
||||||
|
<p class="h3">Invoice Amount: <span class="fw-bold">{% currency_symbol %}{{ invoice.amount_due | currency_format }}</span></p>
|
||||||
|
<p class="h3 text-danger">{{ invoice.get_invoice_status_display | upper }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex justify-content-between">
|
||||||
|
|
||||||
|
|
||||||
|
{# MARK DRAFT #}
|
||||||
|
{% if invoice.can_draft %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_draft_html_id }}')" class="btn btn-link text-info">{% trans 'Mark as Draft' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_draft_url invoice.get_mark_as_draft_message invoice.get_mark_as_draft_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# MARK REVIEW #}
|
||||||
|
{% if invoice.can_review %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_review_html_id }}')" class="btn btn-link text-info">{% trans 'Mark as Review' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_review_url invoice.get_mark_as_review_message invoice.get_mark_as_review_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# MARK APPROVED #}
|
||||||
|
{% if invoice.can_approve %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_approved_html_id }}')" class="btn btn-link text-success">{% trans 'Approve' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_approved_url invoice.get_mark_as_approved_message invoice.get_mark_as_approved_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# MARK PAID #}
|
||||||
|
{% if invoice.can_pay %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_paid_html_id }}')" class="btn btn-link text-success">{% trans 'Mark as Paid' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_paid_url invoice.get_mark_as_paid_message invoice.get_mark_as_paid_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# MARK VOID #}
|
||||||
|
{% if invoice.can_void %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_void_html_id }}')" class="btn btn-link text-danger">{% trans 'Void' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_void_url invoice.get_mark_as_void_message invoice.get_mark_as_void_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# MARK CANCELED #}
|
||||||
|
{% if invoice.can_cancel %}
|
||||||
|
<a onclick="djLedger.toggleModal('{{ invoice.get_mark_as_canceled_html_id }}')" class="btn btn-link text-danger fw-bold">{% trans 'Cancel' %}</a>
|
||||||
|
{% modal_action_v2 invoice invoice.get_mark_as_canceled_url invoice.get_mark_as_canceled_message invoice.get_mark_as_canceled_html_id %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<a href="#">
|
||||||
|
<span class="text-muted">{% icon "ic:baseline-add-circle-outline" 48 %}</span>
|
||||||
|
</a>
|
||||||
|
<h2 class="h3 text-muted">{% trans 'New Invoice' %}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
{% load django_ledger %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-header-title display-4">{% trans 'Journal Entry Detail' %}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="display-4 text-success">{{ journal_entry.je_number }}</h2>
|
||||||
|
|
||||||
|
{% if journal_entry.entity_unit %}
|
||||||
|
<h2 class="display-4 font-weight-light">{{ journal_entry.entity_unit.name }}</h2>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2 class="display-4">{% trans 'Date' %}: {{ journal_entry.timestamp | date }}</h2>
|
||||||
|
|
||||||
|
<h3 class="h4">{% trans 'Posted' %}:
|
||||||
|
{% if journal_entry.is_posted %}
|
||||||
|
<span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
<h3 class="h4">{% trans 'Locked' %}:
|
||||||
|
{% if journal_entry.is_locked %}
|
||||||
|
<span class="text-success">{% icon 'ant-design:check-circle-filled' 24 %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">{% icon 'maki:roadblock-11' 24 %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
{% if journal_entry.activity %}
|
||||||
|
<h3 class="h3">{% trans 'Activity' %}: {{ journal_entry.get_activity_display }}</h3>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.description %}
|
||||||
|
<h4 class="h4 font-weight-light">{{ journal_entry.description }}</h4>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
{% if journal_entry.can_lock %}
|
||||||
|
<a href="{{ journal_entry.get_lock_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}"
|
||||||
|
class="btn btn-success font-weight-bold">{% trans 'Lock' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_unlock %}
|
||||||
|
<a href="{{ journal_entry.get_unlock_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}"
|
||||||
|
class="btn btn-warning font-weight-bold">{% trans 'UnLock' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_post %}
|
||||||
|
<a href="{{ journal_entry.get_post_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}"
|
||||||
|
class="btn btn-success font-weight-bold">{% trans 'Post' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_unpost %}
|
||||||
|
<a href="{{ journal_entry.get_unpost_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}"
|
||||||
|
class="btn btn-danger font-weight-bold">{% trans 'UnPost' %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
21
templates/ledger/journal_entry/journal_entry_form.html
Normal file
21
templates/ledger/journal_entry/journal_entry_form.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Create Journal Entry") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<h3 class="text-center">{% trans "Create Journal Entry" %}</h3>
|
||||||
|
<form id="mainForm" method="post" class="needs-validation">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="row g-3">
|
||||||
|
{{ form|crispy }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 text-center">
|
||||||
|
<button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
|
||||||
|
<a href="{% url 'journalentry_list' ledger.pk %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
119
templates/ledger/journal_entry/journal_entry_list.html
Normal file
119
templates/ledger/journal_entry/journal_entry_list.html
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Journal Entries") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="modal fade" id="confirmModal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-sm">
|
||||||
|
<div class="modal-content ">
|
||||||
|
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
|
||||||
|
<h5 class="mmb-0 me-2 text-warning-dark" id="confirmModalLabel">
|
||||||
|
<i class="fas fa-exclamation-circle text-warning-dark ms-2"></i>
|
||||||
|
{% trans 'Confirm' %}</h5>
|
||||||
|
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close">
|
||||||
|
<span class="fas fa-times"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans 'Are you sure ?' %}
|
||||||
|
<div class="modal-footer flex justify-content-center border-top-0">
|
||||||
|
<form id="confirmForm" method="POST" action="" class="form">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="container-fluid m-0 p-0">
|
||||||
|
<button type="button" class="btn btn-danger btn-sm" data-bs-dismiss="modal"><i class="fa-solid fa-ban"></i> {% trans 'No' %}</button>
|
||||||
|
<button type="submit" class="btn btn-success btn-sm"><i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
|
||||||
|
<h3 class="">{% trans "Journal Entries" %}</h3>
|
||||||
|
<a href="{% url 'journalentry_create' ledger.pk %}" class="btn btn-sm btn-phoenix-primary ">{% trans "Add Journal Entry" %}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-responsive px-1 scrollbar">
|
||||||
|
<table class="table fs-9 mb-0 border-top border-translucent">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Document Number" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Timestamp" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Activity" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Description" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Posted" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Locked" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Transaction Count" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="list">
|
||||||
|
{% for je in journal_entries %}
|
||||||
|
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ je.je_number }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ je.timestamp }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if je.get_activity_display %}
|
||||||
|
{{ je.get_activity_display }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ je.description }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if je.is_posted %}
|
||||||
|
<i class="fa-solid fa-square-check text-success"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if je.is_locked %}
|
||||||
|
<i class="fa-solid fa-lock text-success"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa-solid fa-unlock text-danger"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{{ je.txs_count }}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle white-space-nowrap text-start">
|
||||||
|
<div class="btn-reveal-trigger position-static">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
data-boundary="window"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false"
|
||||||
|
data-bs-reference="parent">
|
||||||
|
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||||
|
<a class="dropdown-item" href="#">{% trans "View" %}</a>
|
||||||
|
<a class="dropdown-item" href="#">{% trans "Edit" %}</a>
|
||||||
|
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="{% url 'journalentry_delete' je.pk %}">{% trans "Delete" %}</a>
|
||||||
|
<a class="dropdown-item" href="{% url 'journalentry_transactions' je.pk %}">{% trans "View" %}</a>
|
||||||
|
<a class="dropdown-item" href="{% url 'journalentry_txs' je.entity_slug je.ledger_id je.pk %}">{% trans "Transactions" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center">{% trans "No Bank Accounts Found" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Transactions") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
{% include 'ledger/journal_entry/includes/card_journal_entry.html' with journal_entry=journal_entry %}
|
||||||
|
</div>
|
||||||
|
<h3 class="mb-3 mt-5"><i class="fa-solid fa-right-left"></i> {% trans "Transactions" %}</h3>
|
||||||
|
|
||||||
|
<div class="table-responsive px-1 scrollbar">
|
||||||
|
<table class="table fs-9 mb-0 border-top border-translucent">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "#" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Timestamp" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Account Name" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Account Code" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Debit" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Credit" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Description" %}</th>
|
||||||
|
</thead>
|
||||||
|
<tbody class="list">
|
||||||
|
{% for transaction in transactions %}
|
||||||
|
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||||
|
|
||||||
|
<td>{{ forloop.counter }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap py-0">{{ transaction.created|date}}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ transaction.account.name }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ transaction.account.code }}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap text-success">{% if transaction.tx_type == "debit" %}<i class="fa-solid fa-circle-up"></i> {{ transaction.amount }}{{ CURRENCY }}{% endif %}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap text-danger">{% if transaction.tx_type == "credit" %}<i class="fa-solid fa-circle-down"></i> {{ transaction.amount }}{{ CURRENCY }}{% endif %}</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">{{ transaction.description }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center">{% trans "No Transactions Found" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
99
templates/ledger/journal_entry/journal_entry_txs.html
Normal file
99
templates/ledger/journal_entry/journal_entry_txs.html
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-12">
|
||||||
|
{% include 'ledger/journal_entry/includes/card_journal_entry.html' with journal_entry=journal_entry %}
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{ view.request.path }}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
{% if txs_formset.non_form_errors %}
|
||||||
|
<div class="alert alert-subtle-warning" role="alert">
|
||||||
|
{{ txs_formset.non_form_errors }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{{ txs_formset.management_form|crispy }}
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>TX Type</th>
|
||||||
|
<th>Amount</th>
|
||||||
|
<th>Description</th>
|
||||||
|
{% if txs_formset.can_delete %}
|
||||||
|
<th>Delete</th>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for f in txs_formset %}
|
||||||
|
<tr>
|
||||||
|
<td class="px-2">
|
||||||
|
{% for hidden_field in f.hidden_fields %}
|
||||||
|
{{ hidden_field }}
|
||||||
|
{% endfor %}
|
||||||
|
{{ f.account|as_crispy_field }}
|
||||||
|
</td>
|
||||||
|
<td>{{ f.tx_type|as_crispy_field }}</td>
|
||||||
|
<td>{{ f.amount|as_crispy_field }}</td>
|
||||||
|
<td>{{ f.description|as_crispy_field }}</td>
|
||||||
|
<td>
|
||||||
|
{% if txs_formset.can_delete %}
|
||||||
|
{{ f.DELETE|as_crispy_field }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 text-center">
|
||||||
|
<button class="btn btn-primary">
|
||||||
|
{% trans 'Save' %}
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-secondary"
|
||||||
|
href="{% url 'journalentry_list' journal_entry.ledger_id %}">
|
||||||
|
{% trans 'Done' %}
|
||||||
|
</a>
|
||||||
|
{% if journal_entry.can_lock %}
|
||||||
|
<a class="btn btn-danger"
|
||||||
|
href="{{ journal_entry.get_action_lock_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}">
|
||||||
|
{% trans 'Lock' %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_unlock %}
|
||||||
|
<a class="btn btn-warning"
|
||||||
|
href="{{ journal_entry.get_action_unlock_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}">
|
||||||
|
{% trans 'UnLock' %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_post %}
|
||||||
|
<a class="btn btn-danger"
|
||||||
|
href="{{ journal_entry.get_action_post_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}">
|
||||||
|
{% trans 'Post' %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if journal_entry.can_unpost %}
|
||||||
|
<a class="btn btn-warning"
|
||||||
|
href="{{ journal_entry.get_action_unpost_url }}?next={% url 'journalentry_txs' journal_entry.entity_slug journal_entry.ledger_id journal_entry.pk %}">
|
||||||
|
{% trans 'UnPost' %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
155
templates/ledger/ledger/ledger_detail.html
Normal file
155
templates/ledger/ledger/ledger_detail.html
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
{% load django_ledger %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="row">
|
||||||
|
{{invoice}}
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
{% include 'ledger/journal_entry/includes/card_invoice.html' with invoice=invoice entity_slug=view.kwargs.entity_slug style='invoice-detail' %}
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<a class="btn btn-info btn-block"
|
||||||
|
href="#">
|
||||||
|
{% trans 'Invoice List' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="d-flex justify-content-around text-center">
|
||||||
|
<div>
|
||||||
|
<p class="text-muted">{% trans 'Cash Account' %}:
|
||||||
|
<a href="#"
|
||||||
|
class="text-danger">{{ invoice.cash_account.code }}</a>
|
||||||
|
</p>
|
||||||
|
<p class="h4">
|
||||||
|
{% currency_symbol %}{{ invoice.get_amount_cash | absolute | currency_format }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if invoice.accrue %}
|
||||||
|
<div>
|
||||||
|
<p class="text-muted">{% trans 'Accounts Receivable' %}:
|
||||||
|
<a href="#"
|
||||||
|
class="text-danger">{{ invoice.prepaid_account.code }}</a>
|
||||||
|
</p>
|
||||||
|
<p class="h4 text-success">
|
||||||
|
{% currency_symbol %}{{ invoice.get_amount_prepaid | currency_format }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-muted">{% trans 'Deferred Revenue' %}:
|
||||||
|
<a href="#"
|
||||||
|
class="text-danger">{{ invoice.unearned_account.code }}</a>
|
||||||
|
</p>
|
||||||
|
<p class="h4 text-danger">
|
||||||
|
{% currency_symbol %}{{ invoice.get_amount_unearned | currency_format }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-muted">Accrued {{ invoice.get_progress_percent }}%</p>
|
||||||
|
<p class="h4">
|
||||||
|
{% currency_symbol %}{{ invoice.get_amount_earned | currency_format }}</p>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div>
|
||||||
|
<p class="text-muted">You Are Owed</p>
|
||||||
|
<p class="h4 text-success">
|
||||||
|
{% currency_symbol %}{{ invoice.get_amount_open | currency_format }}</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-title h3">
|
||||||
|
<span class="me-2">{% icon 'grommet-icons:transaction' 36 %}</span>
|
||||||
|
{% trans 'Invoice Items' %}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans 'Item' %}</th>
|
||||||
|
<th>{% trans 'Unit Cost' %}</th>
|
||||||
|
<th>{% trans 'Quantity' %}</th>
|
||||||
|
<th>{% trans 'Total' %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for invoice_item in itemtxs_qs %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ invoice_item.item_model }}</td>
|
||||||
|
<td>{% currency_symbol %}{{ invoice_item.unit_cost | currency_format }}</td>
|
||||||
|
<td>{{ invoice_item.quantity }}</td>
|
||||||
|
<td>
|
||||||
|
{% currency_symbol %}{{ invoice_item.total_amount | currency_format }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3">{% trans 'Total' %}</th>
|
||||||
|
<th>
|
||||||
|
{% currency_symbol %}{{ total_amount_due | currency_format }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if invoice.is_active %}
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-info">{% trans 'Balance Sheet' %}</a>
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-info">{% trans 'Income Statement' %}</a>
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-info">{% trans 'Cash Flow Statement' %}</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-3">
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-success">
|
||||||
|
{% trans 'Balance Sheet PDF' %}{% icon 'bytesize:download' 24 %}</a>
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-success">
|
||||||
|
{% trans 'Income Statement PDF' %}{% icon 'bytesize:download' 24 %}</a>
|
||||||
|
<a href="#"
|
||||||
|
class="btn btn-success">
|
||||||
|
{% trans 'Cash Flow Statement PDF' %}{% icon 'bytesize:download' 24 %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-title h3">
|
||||||
|
<span class="me-2">{% icon 'grommet-icons:transaction' 36 %}</span>
|
||||||
|
{% trans 'Invoice Transactions' %}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
21
templates/ledger/ledger/ledger_form.html
Normal file
21
templates/ledger/ledger/ledger_form.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Create Ledger") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<h3 class="text-center">{% trans "Create Ledger" %}</h3>
|
||||||
|
<form id="mainForm" method="post" class="needs-validation">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="row g-3">
|
||||||
|
{{ form|crispy }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 text-center">
|
||||||
|
<button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
|
||||||
|
<a href="{% url 'ledger_list' %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
71
templates/ledger/ledger/ledger_list.html
Normal file
71
templates/ledger/ledger/ledger_list.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Ledger") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<h3 class="">{% trans "Ledger" %}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-responsive px-1 scrollbar">
|
||||||
|
<table class="table fs-9 mb-0 border-top border-translucent">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Ledger Name" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Journal Entries" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Earliest Date" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Posted" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Locked" %}</th>
|
||||||
|
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="list">
|
||||||
|
{% for ledger in ledgers %}
|
||||||
|
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
<a href="#">{{ ledger.get_wrapped_model_instance }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
<a class="btn btn-sm btn-primary"
|
||||||
|
href="{% url 'journalentry_list' ledger.pk %}">
|
||||||
|
<i class="fa-solid fa-right-left"></i>
|
||||||
|
<span>
|
||||||
|
<span class="has-text-weight-bold">{{ ledger.journal_entries__count }}</span>
|
||||||
|
<span>{{ _('Journal Entries') }}</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if ledger.earliest_timestamp %}{{ ledger.earliest_timestamp | date }}{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if ledger.is_posted %}
|
||||||
|
<i class="fa-solid fa-square-check text-success"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle product white-space-nowrap">
|
||||||
|
{% if ledger.is_locked %}
|
||||||
|
<i class="fa-solid fa-lock text-success"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="fa-solid fa-unlock text-danger"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center">{% trans "No Bank Accounts Found" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -4,6 +4,23 @@
|
|||||||
{% block title %}{{ _("View Quotation") }}{% endblock title %}
|
{% block title %}{{ _("View Quotation") }}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<!-- View PO Modal -->
|
||||||
|
<div class="modal fade" id="POModal" data-bs-keyboard="true" tabindex="-1" aria-labelledby="POModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
|
||||||
|
<h4 class="mb-0 me-2 text-primary"><i class="fas text-info ms-2"></i></h4>
|
||||||
|
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"><span class="fas fa-times"></span></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
{% include "sales/orders/purchase_order.html" %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer flex justify-content-center border-top-0">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Cancel Modal -->
|
<!-- Cancel Modal -->
|
||||||
<div class="modal fade" id="CancelModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="CancelModalLabel" aria-hidden="true">
|
<div class="modal fade" id="CancelModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="CancelModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog modal-sm">
|
||||||
@ -78,6 +95,7 @@
|
|||||||
{% if estimate.invoicemodel_set.first %}
|
{% if estimate.invoicemodel_set.first %}
|
||||||
<a href="{% url 'invoice_detail' estimate.invoicemodel_set.first.pk %}" class="btn btn-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
|
<a href="{% url 'invoice_detail' estimate.invoicemodel_set.first.pk %}" class="btn btn-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
|
||||||
{{ _("View Invoice")}}</a>
|
{{ _("View Invoice")}}</a>
|
||||||
|
<button class="btn btn-phoenix-primary" data-bs-toggle="modal" data-bs-target="#POModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'View Purchase Order' %}</span></button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if estimate.status == 'draft' %}
|
{% if estimate.status == 'draft' %}
|
||||||
@ -85,13 +103,13 @@
|
|||||||
<button id="mark_as_sent_estimate" class="btn btn-phoenix-secondary" onclick="setFormAction('review')" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Sent' %}</span></button>
|
<button id="mark_as_sent_estimate" class="btn btn-phoenix-secondary" onclick="setFormAction('review')" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Sent' %}</span></button>
|
||||||
{% elif estimate.status == 'in_review' %}
|
{% elif estimate.status == 'in_review' %}
|
||||||
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Accept' %}</span></button>
|
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Accept' %}</span></button>
|
||||||
{% elif estimate.status == 'approved' %}
|
{% elif estimate.status == 'approved' %}
|
||||||
{% if estimate.sale_orders.first %}
|
{% if estimate.sale_orders.first %}
|
||||||
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
|
<a href="{% url 'invoice_create' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
|
<a href="{% url 'create_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
|
||||||
{% comment %} <a href="{% url 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a> {% endcomment %}
|
{% comment %} <a href="{% url 'preview_sale_order' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Preview Sale Order' %}</span></a> {% endcomment %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif estimate.status == 'in_review' %}
|
{% elif estimate.status == 'in_review' %}
|
||||||
<a href="{% url 'estimate_preview' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
<a href="{% url 'estimate_preview' estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -99,7 +117,7 @@
|
|||||||
{% if perms.django_ledger.change_estimatemodel %}
|
{% if perms.django_ledger.change_estimatemodel %}
|
||||||
<button class="btn btn-phoenix-danger" data-bs-toggle="modal" data-bs-target="#CancelModal"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</button>
|
<button class="btn btn-phoenix-danger" data-bs-toggle="modal" data-bs-target="#CancelModal"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-body dark__bg-gray-1100 p-4 mb-4 rounded-2">
|
<div class="bg-body dark__bg-gray-1100 p-4 mb-4 rounded-2">
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load tenhal_tag %}
|
||||||
|
|
||||||
{% block title %}{{ _("View Estimate") }}{% endblock title %}
|
{% block title %}{{ _("View Estimate") }}{% endblock title %}
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
@ -24,7 +25,7 @@
|
|||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-danger"
|
class="btn btn-sm btn-danger"
|
||||||
data-bs-dismiss="modal"><i class="fa-solid fa-ban"></i> {% trans 'No' %}
|
data-bs-dismiss="modal"><i class="fa-solid fa-ban"></i> {% trans 'No' %}
|
||||||
</button>
|
</button>
|
||||||
<form id="confirmForm" method="POST" action="{% url 'invoice_mark_as' invoice.pk %}?mark=accept" class="d-inline">
|
<form id="confirmForm" method="POST" action="{% url 'invoice_mark_as' invoice.pk %}?mark=accept" class="d-inline">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class="btn btn-success btn-sm"><i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}</button>
|
<button type="submit" class="btn btn-success btn-sm"><i class="fa-solid fa-circle-check"></i> {% trans "Yes" %}</button>
|
||||||
@ -88,11 +89,12 @@
|
|||||||
<a href="{% url 'payment_create' invoice.pk %}" class="btn btn-phoenix-success"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-money-bill"></i> {% trans 'Record Payment' %}</span></a>
|
<a href="{% url 'payment_create' invoice.pk %}" class="btn btn-phoenix-success"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-money-bill"></i> {% trans 'Record Payment' %}</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not invoice.is_paid %}
|
{% if not invoice.is_paid %}
|
||||||
<button {% if invoice.is_review %}disabled{% endif %} id="mark_invoice_as_paid" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#mark_as_paid_Modal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-money-check-dollar"></i> {% trans 'Mark as Paid' %}</span></button>
|
<button {% if invoice.is_review or invoice.amount_paid|to_int < invoice.amount_due|to_int %}disabled{% endif %} id="mark_invoice_as_paid" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#mark_as_paid_Modal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-money-check-dollar"></i> {% trans 'Mark as Paid' %}</span></button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url 'invoice_preview' invoice.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
<a href="{% url 'invoice_preview' invoice.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{invoice.amount_owned}}
|
||||||
|
|
||||||
<!-- ============================================-->
|
<!-- ============================================-->
|
||||||
<div class="card mb-5 {% if invoice.is_review %}disabled{% endif %}">
|
<div class="card mb-5 {% if invoice.is_review %}disabled{% endif %}">
|
||||||
|
|||||||
120
templates/sales/orders/purchase_order.html
Normal file
120
templates/sales/orders/purchase_order.html
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
{% block customCSS %}
|
||||||
|
<style>
|
||||||
|
.invoice {
|
||||||
|
width: 100%;
|
||||||
|
height: 400px; /* Fixed height */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between; /* Aligns content to top and bottom */
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.invoice-items {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.invoice-items td {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-top: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
.invoice-items .total td {
|
||||||
|
font-weight: bold;
|
||||||
|
border-top: 2px solid #000;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
margin-top: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
.b-top {
|
||||||
|
border-top: 2px solid #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
<div>
|
||||||
|
<div class="row justify-content-center px-12">
|
||||||
|
<button class="btn btn-primary" type="button" onclick="printDiv('printableArea')">
|
||||||
|
<i class="fa-solid fa-print"></i> {{ _('Print') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="container" id="printableArea">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-10">
|
||||||
|
<div class="card mt-2">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h2 class="card-title">{{ _('Purchase Order') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="invoice p-4">
|
||||||
|
<div class="mb-4">
|
||||||
|
<strong>{{ estimate.customer.customer_name }}</strong><br />
|
||||||
|
Order ID #{{ estimate.sale_orders.first.formatted_order_id }}<br />
|
||||||
|
{{ estimate.sale_orders.first.created|date }}
|
||||||
|
</div>
|
||||||
|
<table class="invoice-items table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<th class="text-end">Price</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="b-top"></tr>
|
||||||
|
{% for item in data.cars %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ item.make }}</td>
|
||||||
|
<td class="text-end">{{ item.unit_price }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
<tr class="b-top">
|
||||||
|
<td>Additionals :</td>
|
||||||
|
</tr>
|
||||||
|
{% for service in data.additionals %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ service.name }}</td>
|
||||||
|
<td class="text-end">{{ service.price_ }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<table class="invoice-items table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th class="text-end">Total</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="total">
|
||||||
|
<td class="text-end" width="80%"></td>
|
||||||
|
<td class="text-end">{{ data.grand_total }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-body text-center"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5">
|
||||||
|
<p>{{ _('Signature') }}:</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block customJS %}
|
||||||
|
<script>
|
||||||
|
function printDiv(divName) {
|
||||||
|
var printContents = document.getElementById(divName).innerHTML
|
||||||
|
var originalContents = document.body.innerHTML
|
||||||
|
|
||||||
|
document.body.innerHTML = printContents
|
||||||
|
|
||||||
|
window.print()
|
||||||
|
|
||||||
|
document.body.innerHTML = originalContents
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user