This commit is contained in:
gitea 2025-01-15 10:16:56 +00:00
commit 03a4e6e498
9 changed files with 305 additions and 85 deletions

View File

@ -36,11 +36,10 @@ def decodevin(vin):
if result:=decode_vin(vin):
return result
elif result:=decode_vin_haikalna(vin):
return result
elif result:=elm(vin):
return result
elif result:=decode_vin_haikalna(vin):
return result
else:
return None

View File

@ -1826,15 +1826,14 @@ class AccountCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
success_message = "Account created successfully."
def form_valid(self, form):
form.instance.entity_model = self.request.user.dealer.entity
dealer = get_user_type(self.request)
form.instance.entity_model = dealer.entity
form.instance.depth = 0
return super().form_valid(form)
def get_form_kwargs(self):
"""
Override this method to pass additional keyword arguments to the form.
"""
entity = self.request.user.dealer.entity
dealer = get_user_type(self.request)
entity = dealer.entity
kwargs = super().get_form_kwargs()
kwargs["coa_model"] = entity.get_default_coa()
@ -1845,6 +1844,28 @@ class AccountDetailView(LoginRequiredMixin, DetailView):
model = AccountModel
template_name = "ledger/coa_accounts/account_detail.html"
context_object_name = "account"
slug_field = 'uuid'
DEFAULT_TXS_DAYS = 30
extra_context = {
'DEFAULT_TXS_DAYS': DEFAULT_TXS_DAYS,
'header_subtitle_icon': 'ic:round-account-tree'
}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
account_model: AccountModel = context['object']
context['header_title'] = f'Account {account_model.code} - {account_model.name}'
context['page_title'] = f'Account {account_model.code} - {account_model.name}'
txs_qs = account_model.transactionmodel_set.all().posted().order_by(
'journal_entry__timestamp'
).select_related(
'journal_entry',
'journal_entry__entity_unit',
'journal_entry__ledger__billmodel',
'journal_entry__ledger__invoicemodel',
)
return context
class AccountUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
@ -1853,7 +1874,7 @@ class AccountUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
template_name = "ledger/coa_accounts/account_form.html"
success_url = reverse_lazy("account_list")
success_message = "Account updated successfully."
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields['_ref_node_id'].widget = HiddenInput()
@ -1879,7 +1900,8 @@ class EstimateListView(LoginRequiredMixin, ListView):
context_object_name = "estimates"
def get_queryset(self):
entity = self.request.user.dealer.entity
dealer = get_user_type(self.request)
entity = dealer.entity
return entity.get_estimates()
@ -2178,7 +2200,7 @@ class DraftInvoiceModelUpdateFormView(LoginRequiredMixin, UpdateView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
kwargs["entity_slug"] = dealer.entity
kwargs["user_model"] = dealer.entity.admin
return kwargs
@ -2192,7 +2214,7 @@ class ApprovedInvoiceModelUpdateFormView(LoginRequiredMixin, UpdateView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
kwargs["entity_slug"] = dealer.entity
kwargs["user_model"] = dealer.entity.admin
return kwargs
@ -2209,7 +2231,7 @@ class PaidInvoiceModelUpdateFormView(LoginRequiredMixin, UpdateView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
kwargs["entity_slug"] = dealer.entity
kwargs["user_model"] = dealer.entity.admin
return kwargs
@ -2245,7 +2267,8 @@ def invoice_mark_as(request, pk):
def invoice_create(request, pk):
estimate = get_object_or_404(EstimateModel, pk=pk)
entity = request.user.dealer.entity
dealer = get_user_type(request)
entity = dealer.entity
if request.method == "POST":
form = forms.InvoiceModelCreateForm(
@ -2343,8 +2366,9 @@ class InvoicePreviewView(LoginRequiredMixin, DetailView):
def PaymentCreateView(request, pk=None):
invoice = InvoiceModel.objects.filter(pk=pk).first()
entity = request.user.dealer.entity
dealer = get_user_type(request)
entity = dealer.entity
form = forms.PaymentForm()
if request.method == "POST":
form = forms.PaymentForm(request.POST)
if form.is_valid():
@ -2425,9 +2449,9 @@ def PaymentCreateView(request, pk=None):
return redirect("invoice_detail", pk=invoice.pk)
except Exception as e:
messages.error(request, f"Error creating payment: {str(e)}")
else:
messages.error(request, f"Invalid form data: {form.errors.as_text()}")
else:
messages.error(request, f"Invalid form data: {str(form.errors)}")
return redirect("invoice_detail", pk=invoice.pk)
form = forms.PaymentForm()
form.initial["amount"] = invoice.amount_due
@ -2471,7 +2495,7 @@ def payment_mark_as_paid(request, pk):
user_model=invoice.ledger.entity.admin,
)
invoice.save()
invoice.ledger.lock_journal_entries()
invoice.ledger.post_journal_entries()
@ -2713,7 +2737,7 @@ class ItemServiceCreateView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
success_url = reverse_lazy("item_service_list")
success_message = _("Service created successfully.")
context_object_name = "service"
def form_valid(self, form):
vat = models.VatRate.objects.get(is_active=True)
form.instance.dealer = get_user_type(self.request.user.dealer)
@ -2725,10 +2749,10 @@ class ItemServiceUpdateView(LoginRequiredMixin,SuccessMessageMixin,UpdateView):
model = models.AdditionalServices
form_class = forms.AdditionalServiceForm
template_name = "items/service/service_create.html"
success_url = reverse_lazy("item_service_list")
success_url = reverse_lazy("item_service_list")
success_message = _("Service updated successfully.")
context_object_name = "service"
def form_valid(self, form):
vat = models.VatRate.objects.get(is_active=True)
form.instance.dealer = get_user_type(self.request.user.dealer)
@ -2755,14 +2779,14 @@ class ItemExpenseCreateView(CreateView):
success_url = reverse_lazy("item_expense_list")
def get_form_kwargs(self):
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
kwargs = super().get_form_kwargs()
kwargs["entity_slug"] = dealer.entity.slug
kwargs["user_model"] = dealer.entity.admin
return kwargs
def form_valid(self, form):
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
form.instance.entity = dealer.entity
return super().form_valid(form)
@ -2774,14 +2798,14 @@ class ItemExpenseUpdateView(UpdateView):
success_url = reverse_lazy("item_expense_list")
def get_form_kwargs(self):
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
kwargs = super().get_form_kwargs()
kwargs["entity_slug"] = dealer.entity.slug
kwargs["user_model"] = dealer.entity.admin
return kwargs
def form_valid(self, form):
dealer = get_user_type(self.request.user.dealer)
dealer = get_user_type(self.request)
form.instance.entity = dealer.entity
return super().form_valid(form)

View File

@ -346,7 +346,7 @@
}
document.addEventListener("DOMContentLoaded", function () {
const csrfToken = getCookie("token");
const csrfToken = getCookie("csrftoken");
const vinInput = document.getElementById("{{ form.vin.id_for_label }}");
const decodeVinBtn = document.getElementById("decodeVinBtn");

View File

@ -12,9 +12,9 @@
<h1 class="fs-5 pt-3">{{ inventory.total_cars }}</h1>
<p class="fs-9 mb-0">{% trans "Total Cars in Inventory" %}</p>
</div>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end-md border-bottom pb-4 pb-xxl-0"><span class="uil fs-5 lh-1 uil-envelope-upload text-info"></span>
<h1 class="fs-5 pt-3">1,866</h1>
<p class="fs-9 mb-0">Emails Sent</p>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-end-xxl-0 border-bottom-xxl-0 border-end-md border-bottom pb-4 pb-xxl-0"><span class="uil fs-5 lh-1 uil-lock-alt text-info"></span>
<h1 class="fs-5 pt-3">2</h1>
<p class="fs-9 mb-0">{{ _("Reserved")}}</p>
</div>
<div class="col-6 col-md-4 col-xxl-2 text-center border-translucent border-start-xxl border-bottom-xxl-0 border-bottom border-end border-end-md-0 pb-4 pb-xxl-0 pt-4 pt-md-0"><span class="uil fs-5 lh-1 uil-envelopes text-primary"></span>
<h1 class="fs-5 pt-3">1,366</h1>

View File

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}{{ _("View Account") }}{% endblock title %}
{% block title %}{{ page_title }}{% endblock title %}
{% block content %}
<!-- Delete Modal -->
@ -40,8 +40,8 @@
<div class="row my-5">
<div class="card rounded ">
<div class="card-header bg-primary text-white ">
<p class="mb-0">{{ _("Bank Account Details") }}</p>
<div class="card-header ">
<p class="mb-0">{{ header_title|upper }}</p>
</div>
<div class="card-body">
<div class="row">
@ -54,6 +54,66 @@
<p><strong>{{ _("Active") }}:</strong> {{ account.active }}</p>
</div>
</div>
<div class="row">
<div class="col">
<table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75">
<tr>
<th class="has-text-centered">{{ _("JE Number")}}</th>
<th class="has-text-centered">{{ _("Date") }}</th>
<th class="has-text-centered">{{ _("Debit") }}</th>
<th class="has-text-centered">{{ _("Credit") }}</th>
<th class="has-text-centered">{{ _("Description") }}</th>
<th class="has-text-centered">{{ _("Unit") }}</th>
<th class="has-text-centered">{{ _("Actions") }}</th>
</tr>
{% for tx in transactions %}
<tr class="has-text-centered">
<td>{{ tx.journal_entry.je_number }}</td>
<td>{{ tx.journal_entry.timestamp }}</td>
<td>{% if tx.tx_type == 'debit' %}${{ tx.amount }}{% endif %}</td>
<td>{% if tx.tx_type == 'credit' %}${{ tx.amount }}{% endif %}</td>
<td>{{ tx.description }}</td>
<td>{{ tx.journal_entry.entity_unit.name }}</td>
<td>
<div class="dropdown is-right is-hoverable" id="tx-action-{{ tx.uuid }}">
<div class="dropdown-trigger">
<button class="button is-small is-rounded is-outlined"
aria-haspopup="true"
aria-controls="dropdown-menu">
<span>{% trans 'Actions' %}</span>
<span class="icon is-small fas fa-arrow-down"></span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu-{{ tx.uuid }}" role="menu">
<div class="dropdown-content">
{# TODO: These URLs need to be replaced with the future mode method that generates it. #}
<a href="{% url 'django_ledger:je-detail' entity_slug=entity_slug ledger_pk=tx.journal_entry.ledger.uuid je_pk=tx.journal_entry.uuid %}"
class="dropdown-item has-text-success">View JE</a>
{% if tx.journal_entry.ledger.billmodel %}
<a href="{% url 'django_ledger:bill-detail' entity_slug=entity_slug bill_pk=tx.journal_entry.ledger.billmodel.uuid %}"
class="dropdown-item has-text-primary">View Bill</a>
{% elif tx.journal_entry.ledger.invoicemodel %}
<a href="{% url 'django_ledger:invoice-detail' entity_slug=entity_slug invoice_pk=tx.journal_entry.ledger.invoicemodel.uuid %}"
class="dropdown-item has-text-info">View Invoice</a>
{% endif %}
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
<tr class="has-text-weight-bold">
<td></td>
<td class="has-text-right">Total</td>
<td class="has-text-centered">${{ total_credits }}</td>
<td class="has-text-centered">${{ total_debits }}</td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
<div class="card-footer d-flex ">
<a class="btn btn-sm btn-primary me-1" href="{% url 'account_update' account.pk %}">

View File

@ -1,9 +1,182 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}{{ _("Chart of Accounts") }}{% endblock title %}
{% load i18n %}
{% block title %}{% trans "Accounts" %}{% endblock title %}
{% block accounts %}
<a class="nav-link active fw-bold">
{% trans "Accounts"|capfirst %}
<span class="visually-hidden">(current)</span>
</a>
{% endblock %}
{% block content %}
<div class="d-flex flex-column min-vh-100">
<div class="d-flex flex-column flex-sm-grow-1 ms-sm-14 p-4">
<main class="d-grid gap-4 p-1">
<!-- Search Bar -->
<div class="row g-4">
<div class="col-12">
<div class="row-fluid p-2">
<form method="get">
<div class="input-group input-group-sm">
<button class="btn btn-sm btn-secondary rounded-start" type="submit">
{% trans "search" %}
</button>
<input type="text"
name="q"
class="form-control form-control-sm rounded-end"
value="{{ request.GET.q }}"
placeholder="{% trans 'Search accounts...' %}" />
{% if request.GET.q %}
<a href="{% url request.resolver_match.view_name %}"
class="btn btn-sm btn-outline-danger ms-1 rounded">
<i class="bi bi-x-lg"></i>
</a>
{% endif %}
</div>
</form>
</div>
</div>
</div>
<!-- Customer Table -->
{% if page_obj.object_list %}
<div id="accountsTable">
<div class="table-responsive">
<table class="table table-sm fs-9 mb-0">
<thead>
<tr class="bg-body-highlight">
<th class="border-top border-translucent ps-3">{% trans "Account Name" %}</th>
<th class="border-top border-translucent">{% trans "Code" %}</th>
<th class="border-top border-translucent text-end pe-3">{% trans "Balance Type" %}</th>
<th class="border-top border-translucent text-end pe-3">{% trans "Active" %}</th>
<th class="border-top border-translucent text-end align-middle pe-0 ps-4" scope="col"></th>
</tr>
</thead>
<tbody class="list">
{% for account in accounts %}
<div class="modal fade" id="deleteModal"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabindex="-1"
aria-labelledby="deleteModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">
{% trans "Delete Account" %}
<span data-feather="alert-circle"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<p class="mb-0 text-danger fw-bold">
{% trans "Are you sure you want to delete this Account?" %}
</p>
<div class="d-grid gap-2">
<button type="button" class="btn btn-phoenix-secondary btn-sm" data-bs-dismiss="modal">
{% trans "No" %}
</button>
<a type="button" class="btn btn-phoenix-danger btn-sm" href="{% url 'account_delete' account.uuid %}">
{% trans "Yes" %}
</a>
</div>
</div>
</div>
</div>
</div>
<tr>
<td class="align-middle ps-3">{{ account.name }}</td>
<td class="align-middle">{{ account.code }}</td>
<td class="align-middle text-end py-3 pe-3">
{% if account.balance_type == 'debit' %}
<div class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="fw-bold">{{ _("Debit") }}</span><span class="ms-1 fas fa-arrow-circle-down"></span></div>
{% else %}
<div class="badge badge-phoenix fs-10 badge-phoenix-danger"><span class="fw-bold">{{ _("Credit") }}</span><span class="ms-1 fas fa-arrow-circle-up"></span></div>
{% endif %}
</td>
<td class="align-middle text-end py-3 pe-3">
{% if account.active %}
<span class="fw-bold text-success fas fa-check-circle"></span>
{% else %}
<span class="fw-bold text-danger far fa-times-circle"></span>
{% endif %}
</td>
<td>
<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 href="{% url 'account_detail' account.uuid %}" class="dropdown-item text-success-dark">
{% trans "View" %}
</a>
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>
</div>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="5" class="text-center text-muted">
{% trans "No account found." %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="d-flex justify-content-between mt-3"><span class="d-none d-sm-inline-block" data-list-info="data-list-info">{{ page_obj.start_index }} {{ _("to") }} {{ page_obj.end_index }}<span class="text-body-tertiary"> {{ _("Items of")}} </span>{{ page_obj.paginator.count }}</span>
<div class="d-flex">
<nav aria-label="Page navigation">
<ul class="pagination mb-0">
{% if page_obj.has_previous %}
<li class="page-item py-0">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true"><span class="fas fa-chevron-left"></span></span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true"><span class="fas fa-chevron-left"></span></span>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active"><a class="page-link" href="?page={{ num }}">{{ num }}</a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true"><span class="fas fa-chevron-right"></span></span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true"><span class="fas fa-chevron-right"></span></span>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
</div>
</div>
{% endif %}
</main>
<div class="row mt-4 mx-4">
<div class="d-flex justify-content-between mb-2 p-6">
<span></span>
@ -11,12 +184,12 @@
<a href="{% url 'account_create' %}" class="btn btn-sm btn-success ">{% trans "Add Account" %}</a>
</div>
<div class="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-7 border-y">
<div class="table-responsive mx-n1 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 "Name" %}</th>
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Name" %}</th>
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Account Number" %}</th>
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Balance Type" %}</th>
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Active" %}</th>
@ -25,17 +198,17 @@
</thead>
<tbody class="list">
{% for account in accounts %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle product white-space-nowrap">{{ account.name }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.code }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.balance_type|capfirst }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.active }}</td>
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle product white-space-nowrap">{{ account.name }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.code }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.balance_type|capfirst }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ account.active }}</td>
<td class="">
<a href="{% url 'account_update' account.pk %}"
<a href="{% url 'account_update' account.pk %}"
class="btn btn-sm btn-phoenix-success">
{% trans "Update" %}
</a>
</td>
</td>
</tr>
{% empty %}
<tr>
@ -45,7 +218,7 @@
</tbody>
</table>
</div>
<div class="d-flex justify-content-center">
<div class="d-flex justify-content-center">
</div>
</div>
</div>

View File

@ -55,43 +55,7 @@
</table>
</div>
{% if is_paginated %}
<nav aria-label="Page navigation">
<ul class="pagination mb-0">
{% if page_obj.has_previous %}
<li class="page-item py-0">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true"><span class="fas fa-chevron-left"></span></span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true"><span class="fas fa-chevron-left"></span></span>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active"><a class="page-link" href="?page={{ num }}">{{ num }}</a></li>
{% else %}
<li class="page-item"><a class="page-link" href="?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true"><span class="fas fa-chevron-right"></span></span>
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true"><span class="fas fa-chevron-right"></span></span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% include 'partials/pagination.html' %}
{% endif %}
</div>
{% endblock %}