some changes
This commit is contained in:
parent
78ffb13703
commit
9437fa10ce
@ -179,6 +179,10 @@ urlpatterns = [
|
|||||||
path('items/expeneses/', views.ItemExpenseListView.as_view(), name='item_expense_list'),
|
path('items/expeneses/', views.ItemExpenseListView.as_view(), name='item_expense_list'),
|
||||||
path('items/expeneses/create/', views.ItemExpenseCreateView.as_view(), name='item_expense_create'),
|
path('items/expeneses/create/', views.ItemExpenseCreateView.as_view(), name='item_expense_create'),
|
||||||
path('items/expeneses/<uuid:pk>/update/', views.ItemExpenseUpdateView.as_view(), name='item_expense_update'),
|
path('items/expeneses/<uuid:pk>/update/', views.ItemExpenseUpdateView.as_view(), name='item_expense_update'),
|
||||||
|
# Bills
|
||||||
|
path('items/bills/', views.BillListView.as_view(), name='bill_list'),
|
||||||
|
path('items/bills/create/', views.BillCreateView.as_view(), name='bill_create'),
|
||||||
|
# path('items/bills/<uuid:pk>/update/', views.ItemExpenseUpdateView.as_view(), name='item_expense_update'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,11 +14,13 @@ from django_ledger.models import (
|
|||||||
CustomerModel,
|
CustomerModel,
|
||||||
LedgerModel,
|
LedgerModel,
|
||||||
ItemModel,
|
ItemModel,
|
||||||
|
BillModel
|
||||||
)
|
)
|
||||||
from django_ledger.forms.bank_account import (
|
from django_ledger.forms.bank_account import (
|
||||||
BankAccountCreateForm,
|
BankAccountCreateForm,
|
||||||
BankAccountUpdateForm,
|
BankAccountUpdateForm,
|
||||||
)
|
)
|
||||||
|
from django_ledger.forms.bill import BillModelCreateForm
|
||||||
from django_ledger.forms.invoice import (
|
from django_ledger.forms.invoice import (
|
||||||
DraftInvoiceModelUpdateForm,
|
DraftInvoiceModelUpdateForm,
|
||||||
ApprovedInvoiceModelUpdateForm,
|
ApprovedInvoiceModelUpdateForm,
|
||||||
@ -89,7 +91,6 @@ import numpy as np
|
|||||||
from pyzbar.pyzbar import decode
|
from pyzbar.pyzbar import decode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
@ -439,7 +440,7 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
|||||||
return JsonResponse(serialized_options, safe=False)
|
return JsonResponse(serialized_options, safe=False)
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(csrf_exempt, name='dispatch')
|
@method_decorator(csrf_exempt, name="dispatch")
|
||||||
class SearchCodeView(View):
|
class SearchCodeView(View):
|
||||||
template_name = "inventory/scan_vin.html"
|
template_name = "inventory/scan_vin.html"
|
||||||
|
|
||||||
@ -448,27 +449,29 @@ class SearchCodeView(View):
|
|||||||
return render(request, self.template_name)
|
return render(request, self.template_name)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
image_file = request.FILES.get('image')
|
image_file = request.FILES.get("image")
|
||||||
|
|
||||||
if image_file:
|
if image_file:
|
||||||
print("image received!")
|
print("image received!")
|
||||||
image = cv2.imdecode(np.frombuffer(image_file.read(), np.uint8), cv2.IMREAD_COLOR)
|
image = cv2.imdecode(
|
||||||
|
np.frombuffer(image_file.read(), np.uint8), cv2.IMREAD_COLOR
|
||||||
|
)
|
||||||
decoded_objects = decode(image)
|
decoded_objects = decode(image)
|
||||||
if decoded_objects:
|
if decoded_objects:
|
||||||
print("image decoded!")
|
print("image decoded!")
|
||||||
print(decoded_objects[0])
|
print(decoded_objects[0])
|
||||||
code = decoded_objects[0].data.decode('utf-8')
|
code = decoded_objects[0].data.decode("utf-8")
|
||||||
print("code received!")
|
print("code received!")
|
||||||
print(code)
|
print(code)
|
||||||
car = get_object_or_404(models.Car, vin=code)
|
car = get_object_or_404(models.Car, vin=code)
|
||||||
name = car.id_car_make.get_local_name
|
name = car.id_car_make.get_local_name
|
||||||
print(name)
|
print(name)
|
||||||
return redirect('car_detail', pk=car.pk)
|
return redirect("car_detail", pk=car.pk)
|
||||||
else:
|
else:
|
||||||
print("back to else statement")
|
print("back to else statement")
|
||||||
return JsonResponse({'success': False, 'error': 'No code detected'})
|
return JsonResponse({"success": False, "error": "No code detected"})
|
||||||
else:
|
else:
|
||||||
return JsonResponse({'success': False, 'error': 'No image provided'})
|
return JsonResponse({"success": False, "error": "No image provided"})
|
||||||
|
|
||||||
|
|
||||||
class CarInventory(LoginRequiredMixin, ListView):
|
class CarInventory(LoginRequiredMixin, ListView):
|
||||||
@ -638,7 +641,9 @@ class CarFinanceCreateView(LoginRequiredMixin, CreateView):
|
|||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
form.fields["additional_finances"].queryset = models.AdditionalServices.objects.filter(dealer=dealer)
|
form.fields[
|
||||||
|
"additional_finances"
|
||||||
|
].queryset = models.AdditionalServices.objects.filter(dealer=dealer)
|
||||||
return form
|
return form
|
||||||
|
|
||||||
# def get_initial(self):
|
# def get_initial(self):
|
||||||
@ -1844,27 +1849,35 @@ class AccountDetailView(LoginRequiredMixin, DetailView):
|
|||||||
model = AccountModel
|
model = AccountModel
|
||||||
template_name = "ledger/coa_accounts/account_detail.html"
|
template_name = "ledger/coa_accounts/account_detail.html"
|
||||||
context_object_name = "account"
|
context_object_name = "account"
|
||||||
slug_field = 'uuid'
|
slug_field = "uuid"
|
||||||
DEFAULT_TXS_DAYS = 30
|
DEFAULT_TXS_DAYS = 30
|
||||||
extra_context = {
|
extra_context = {
|
||||||
'DEFAULT_TXS_DAYS': DEFAULT_TXS_DAYS,
|
"DEFAULT_TXS_DAYS": DEFAULT_TXS_DAYS,
|
||||||
'header_subtitle_icon': 'ic:round-account-tree'
|
"header_subtitle_icon": "ic:round-account-tree",
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
account_model: AccountModel = context['object']
|
account_model: AccountModel = context["object"]
|
||||||
context['header_title'] = f'Account {account_model.code} - {account_model.name}'
|
context["header_title"] = f"Account {account_model.code} - {account_model.name}"
|
||||||
context['page_title'] = f'Account {account_model.code} - {account_model.name}'
|
context["page_title"] = f"Account {account_model.code} - {account_model.name}"
|
||||||
context['total_debits'] = sum(x.amount for x in account_model.transactionmodel_set.filter(tx_type='debit'))
|
context["total_debits"] = sum(
|
||||||
context['total_credits'] = sum(x.amount for x in account_model.transactionmodel_set.filter(tx_type='credit'))
|
x.amount for x in account_model.transactionmodel_set.filter(tx_type="debit")
|
||||||
txs_qs = account_model.transactionmodel_set.all().posted().order_by(
|
)
|
||||||
'journal_entry__timestamp'
|
context["total_credits"] = sum(
|
||||||
).select_related(
|
x.amount
|
||||||
'journal_entry',
|
for x in account_model.transactionmodel_set.filter(tx_type="credit")
|
||||||
'journal_entry__entity_unit',
|
)
|
||||||
'journal_entry__ledger__billmodel',
|
txs_qs = (
|
||||||
'journal_entry__ledger__invoicemodel',
|
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
|
return context
|
||||||
@ -1879,10 +1892,11 @@ class AccountUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
|
|||||||
|
|
||||||
def get_form(self, form_class=None):
|
def get_form(self, form_class=None):
|
||||||
form = super().get_form(form_class)
|
form = super().get_form(form_class)
|
||||||
form.fields['_ref_node_id'].widget = HiddenInput()
|
form.fields["_ref_node_id"].widget = HiddenInput()
|
||||||
form.fields['_position'].widget = HiddenInput()
|
form.fields["_position"].widget = HiddenInput()
|
||||||
return form
|
return form
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def account_delete(request, pk):
|
def account_delete(request, pk):
|
||||||
account = get_object_or_404(AccountModel, pk=pk)
|
account = get_object_or_404(AccountModel, pk=pk)
|
||||||
@ -2262,7 +2276,9 @@ def invoice_mark_as(request, pk):
|
|||||||
if not invoice.can_approve():
|
if not invoice.can_approve():
|
||||||
messages.error(request, "invoice is not ready for approval")
|
messages.error(request, "invoice is not ready for approval")
|
||||||
return redirect("invoice_detail", pk=invoice.pk)
|
return redirect("invoice_detail", pk=invoice.pk)
|
||||||
invoice.mark_as_approved(entity_slug=dealer.entity.slug, user_model=dealer.entity.admin)
|
invoice.mark_as_approved(
|
||||||
|
entity_slug=dealer.entity.slug, user_model=dealer.entity.admin
|
||||||
|
)
|
||||||
invoice.save()
|
invoice.save()
|
||||||
return redirect("invoice_detail", pk=invoice.pk)
|
return redirect("invoice_detail", pk=invoice.pk)
|
||||||
|
|
||||||
@ -2306,9 +2322,9 @@ def invoice_create(request, pk):
|
|||||||
"unit_cost": unit_cost,
|
"unit_cost": unit_cost,
|
||||||
"unit_revenue": unit_cost,
|
"unit_revenue": unit_cost,
|
||||||
"quantity": item.ce_quantity,
|
"quantity": item.ce_quantity,
|
||||||
"total_amount": grand_total
|
"total_amount": grand_total,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
invoice_itemtxs = {
|
invoice_itemtxs = {
|
||||||
i.get("item_number"): {
|
i.get("item_number"): {
|
||||||
"unit_cost": i.get("unit_cost"),
|
"unit_cost": i.get("unit_cost"),
|
||||||
@ -2567,9 +2583,9 @@ class LeadDetailView(DetailView):
|
|||||||
class LeadCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin):
|
class LeadCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin):
|
||||||
model = models.Lead
|
model = models.Lead
|
||||||
form_class = forms.LeadForm
|
form_class = forms.LeadForm
|
||||||
template_name = 'crm/leads/lead_form.html'
|
template_name = "crm/leads/lead_form.html"
|
||||||
# success_message = "Lead created successfully!"
|
# success_message = "Lead created successfully!"
|
||||||
success_url = reverse_lazy('lead_list')
|
success_url = reverse_lazy("lead_list")
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
print("Form data:", form.cleaned_data) # Debug form data
|
print("Form data:", form.cleaned_data) # Debug form data
|
||||||
@ -2579,9 +2595,11 @@ class LeadCreateView(CreateView, SuccessMessageMixin, LoginRequiredMixin):
|
|||||||
|
|
||||||
|
|
||||||
def get_car_models(request):
|
def get_car_models(request):
|
||||||
make_id = request.GET.get('id_car_make')
|
make_id = request.GET.get("id_car_make")
|
||||||
if make_id:
|
if make_id:
|
||||||
car_models = models.CarModel.objects.filter(id_car_make=make_id).values('id_car_model', 'name', 'arabic_name')
|
car_models = models.CarModel.objects.filter(id_car_make=make_id).values(
|
||||||
|
"id_car_model", "name", "arabic_name"
|
||||||
|
)
|
||||||
return JsonResponse(list(car_models), safe=False)
|
return JsonResponse(list(car_models), safe=False)
|
||||||
return JsonResponse([], safe=False)
|
return JsonResponse([], safe=False)
|
||||||
|
|
||||||
@ -2589,8 +2607,9 @@ def get_car_models(request):
|
|||||||
class LeadUpdateView(UpdateView):
|
class LeadUpdateView(UpdateView):
|
||||||
model = models.Lead
|
model = models.Lead
|
||||||
form_class = forms.LeadForm
|
form_class = forms.LeadForm
|
||||||
template_name = 'crm/leads/lead_form.html'
|
template_name = "crm/leads/lead_form.html"
|
||||||
success_url = reverse_lazy('lead_list')
|
success_url = reverse_lazy("lead_list")
|
||||||
|
|
||||||
|
|
||||||
class LeadDeleteView(DeleteView):
|
class LeadDeleteView(DeleteView):
|
||||||
model = models.Lead
|
model = models.Lead
|
||||||
@ -2742,7 +2761,7 @@ def fetch_notifications(request):
|
|||||||
return JsonResponse({"notifications": notifications_data})
|
return JsonResponse({"notifications": notifications_data})
|
||||||
|
|
||||||
|
|
||||||
class ItemServiceCreateView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
|
class ItemServiceCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
model = models.AdditionalServices
|
model = models.AdditionalServices
|
||||||
form_class = forms.AdditionalServiceForm
|
form_class = forms.AdditionalServiceForm
|
||||||
template_name = "items/service/service_create.html"
|
template_name = "items/service/service_create.html"
|
||||||
@ -2757,7 +2776,8 @@ class ItemServiceCreateView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
|
|||||||
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
form.instance.price = (form.instance.price * vat.rate) + form.instance.price
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
class ItemServiceUpdateView(LoginRequiredMixin,SuccessMessageMixin,UpdateView):
|
|
||||||
|
class ItemServiceUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||||
model = models.AdditionalServices
|
model = models.AdditionalServices
|
||||||
form_class = forms.AdditionalServiceForm
|
form_class = forms.AdditionalServiceForm
|
||||||
template_name = "items/service/service_create.html"
|
template_name = "items/service/service_create.html"
|
||||||
@ -2833,6 +2853,36 @@ class ItemExpenseListView(ListView):
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
class BillListView(ListView):
|
||||||
|
model = ItemModel
|
||||||
|
template_name = "ledger/bills/bill_list.html"
|
||||||
|
context_object_name = "bills"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
|
items = dealer.entity.get_bills()
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
class BillCreateView(LoginRequiredMixin,SuccessMessageMixin,CreateView):
|
||||||
|
model = BillModel
|
||||||
|
form_class = BillModelCreateForm
|
||||||
|
template_name = "ledger/bills/bill_form.html"
|
||||||
|
success_url = reverse_lazy("bill_list")
|
||||||
|
success_message = _("Bill created successfully.")
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
dealer = get_user_type(self.request)
|
||||||
|
kwargs = super().get_form_kwargs()
|
||||||
|
kwargs["entity_model"] = dealer.entity
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# dealer = get_user_type(self.request)
|
||||||
|
# form.instance.entity = dealer.entity
|
||||||
|
# return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionPlans(ListView):
|
class SubscriptionPlans(ListView):
|
||||||
model = models.SubscriptionPlan
|
model = models.SubscriptionPlan
|
||||||
template_name = "subscriptions/subscription_plan.html"
|
template_name = "subscriptions/subscription_plan.html"
|
||||||
|
|||||||
122
templates/ledger/bills/bill_detail.html
Normal file
122
templates/ledger/bills/bill_detail.html
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ page_title }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Delete Modal -->
|
||||||
|
<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 rounded">
|
||||||
|
<div class="modal-body d-flex justify-content-center">
|
||||||
|
<h1 class="text-danger me-2"><i class="bi bi-exclamation-diamond-fill"></i></h1>
|
||||||
|
<span class="text-danger">{% trans 'Are you sure you want to delete this account?' %}</span>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">{% trans 'No' %}</button>
|
||||||
|
<div class="btn btn-sm btn-danger">
|
||||||
|
<form action="{% url 'account_delete' account.pk %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger">{% trans 'Yes' %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-5">
|
||||||
|
<div class="card rounded">
|
||||||
|
<div class="card-header">
|
||||||
|
<p class="mb-0">{{ header_title|upper }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p>
|
||||||
|
<strong>{{ _('Account Name') }}:</strong> {{ account.name }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>{{ _('Account Code') }}:</strong> {{ account.code }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p>
|
||||||
|
<strong>{{ _('Balance Type') }}:</strong> {{ account.balance_type }}
|
||||||
|
</p>
|
||||||
|
<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 account.transactionmodel_set.all %}
|
||||||
|
<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="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="{% url 'payment_details' tx.journal_entry.pk %}">{% trans 'view'|capfirst %}</a>
|
||||||
|
</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_debits }}</td>
|
||||||
|
<td class="has-text-centered">${{ total_credits }}</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 %}">
|
||||||
|
<!-- <i class="bi bi-pencil-square"></i> -->
|
||||||
|
{{ _('Edit') }}
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-danger me-1" data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||||
|
<!-- <i class="bi bi-trash-fill"></i> -->
|
||||||
|
{{ _('Delete') }}
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-secondary" href="{% url 'account_list' %}">
|
||||||
|
<!-- <i class="bi bi-arrow-left-square-fill"></i> -->
|
||||||
|
{% trans 'Back to List' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
38
templates/ledger/bills/bill_form.html
Normal file
38
templates/ledger/bills/bill_form.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% block title %}{% trans "account" %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row my-5">
|
||||||
|
<!-- Display Form Errors -->
|
||||||
|
<div class="card shadow rounded">
|
||||||
|
<div class="card-header bg-primary text-white">
|
||||||
|
<p class="mb-0">
|
||||||
|
{% if account.created %}
|
||||||
|
<!--<i class="bi bi-pencil-square"></i>-->
|
||||||
|
{{ _("Edit Account") }}
|
||||||
|
{% else %}
|
||||||
|
<!--<i class="bi bi-person-plus"></i> -->
|
||||||
|
{{ _("Add Account") }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" class="form" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
{% for error in form.errors %}
|
||||||
|
<div class="text-danger">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<button class="btn btn-sm btn-success me-1" type="submit">
|
||||||
|
{{ _("Save") }}
|
||||||
|
</button>
|
||||||
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger">{% trans "Cancel"|capfirst %}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
165
templates/ledger/bills/bill_list.html
Normal file
165
templates/ledger/bills/bill_list.html
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}
|
||||||
|
{% trans 'Bills' %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block bills %}
|
||||||
|
<a class="nav-link active fw-bold">
|
||||||
|
{% trans 'Bills'|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 bills...' %}" />
|
||||||
|
{% 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 bill in bills %}
|
||||||
|
<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 Bill' %}
|
||||||
|
<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 Bill?' %}
|
||||||
|
</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' bill.uuid %}">{% trans 'Yes' %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<tr>
|
||||||
|
<td class="align-middle ps-3">{{ bill.name }}</td>
|
||||||
|
<td class="align-middle">{{ bill.code }}</td>
|
||||||
|
<td class="align-middle text-end py-3 pe-3">
|
||||||
|
{% if bill.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 bill.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 'bill_detail' bill.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 bill 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>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user