save
This commit is contained in:
parent
569fa3f7fb
commit
b2c609afa6
@ -9,6 +9,7 @@ from phonenumber_field.phonenumber import PhoneNumber
|
|||||||
from .mixins import AddClassMixin
|
from .mixins import AddClassMixin
|
||||||
from django.forms.models import inlineformset_factory
|
from django.forms.models import inlineformset_factory
|
||||||
from django_ledger.forms.invoice import InvoiceModelCreateForm as InvoiceModelCreateFormBase
|
from django_ledger.forms.invoice import InvoiceModelCreateForm as InvoiceModelCreateFormBase
|
||||||
|
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
|
||||||
from .models import (
|
from .models import (
|
||||||
Dealer,
|
Dealer,
|
||||||
# Branch,
|
# Branch,
|
||||||
@ -637,4 +638,13 @@ class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
|
|||||||
self.fields['cash_account'].widget = forms.HiddenInput()
|
self.fields['cash_account'].widget = forms.HiddenInput()
|
||||||
self.fields['prepaid_account'].widget = forms.HiddenInput()
|
self.fields['prepaid_account'].widget = forms.HiddenInput()
|
||||||
self.fields['unearned_account'].widget = forms.HiddenInput()
|
self.fields['unearned_account'].widget = forms.HiddenInput()
|
||||||
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
|
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
|
||||||
|
|
||||||
|
class BillModelCreateForm(BillModelCreateFormBase):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.fields['cash_account'].widget = forms.HiddenInput()
|
||||||
|
self.fields['prepaid_account'].widget = forms.HiddenInput()
|
||||||
|
self.fields['unearned_account'].widget = forms.HiddenInput()
|
||||||
|
self.fields['date_draft'] = forms.DateField(widget=DateInput(attrs={'type': 'date'}))
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
from django.forms import DateField, DateInput, HiddenInput, TextInput
|
from django.forms import DateField, DateInput, HiddenInput, TextInput
|
||||||
|
from django_ledger.forms.bill import ApprovedBillModelUpdateForm, InReviewBillModelUpdateForm
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django_ledger.models import (
|
from django_ledger.models import (
|
||||||
|
|||||||
@ -1,122 +1,273 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}{{ _("View Bill") }}{% endblock title %}
|
||||||
{{ page_title }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- Delete Modal -->
|
<div class="modal fade" id="mark_as_approved_Modal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||||
<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-dialog modal-sm">
|
<div class="modal-content">
|
||||||
<div class="modal-content rounded">
|
<div class="modal-header bg-primary">
|
||||||
<div class="modal-body d-flex justify-content-center">
|
<h5 class="modal-title text-light" id="confirmModalLabel">{% trans 'Confirm' %}</h5>
|
||||||
<h1 class="text-danger me-2"><i class="bi bi-exclamation-diamond-fill"></i></h1>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
<span class="text-danger">{% trans 'Are you sure you want to delete this account?' %}</span>
|
</div>
|
||||||
</div>
|
<div class="modal-body">
|
||||||
<div class="btn-group">
|
{% trans 'Are you sure' %}
|
||||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">{% trans 'No' %}</button>
|
<div class="modal-footer">
|
||||||
<div class="btn btn-sm btn-danger">
|
<button type="button"
|
||||||
<form action="{% url 'account_delete' account.pk %}" method="post">
|
class="btn btn-sm btn-danger"
|
||||||
{% csrf_token %}
|
data-bs-dismiss="modal">
|
||||||
<button type="submit" class="btn btn-sm btn-danger">{% trans 'Yes' %}</button>
|
{% trans 'No' %}
|
||||||
|
</button>
|
||||||
|
<form id="confirmForm" method="POST" action="{% url 'bill_mark_as_approved' bill.pk %}" class="d-inline">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="btn btn-success btn-sm">{% trans "Yes" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- ============================================-->
|
||||||
|
<div class="modal fade" id="mark_as_paid_Modal" tabindex="-1" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-sm">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header bg-primary">
|
||||||
|
<h5 class="modal-title text-light" id="confirmModalLabel">{% trans 'Confirm' %}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans 'Are you sure' %}
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-danger"
|
||||||
|
data-bs-dismiss="modal">
|
||||||
|
{% trans 'No' %}
|
||||||
|
</button>
|
||||||
|
<form id="confirmForm" method="POST" action="{% url 'bill_mark_as_paid' bill.pk %}" class="d-inline">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="btn btn-success btn-sm">{% trans "Yes" %}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ============================================-->
|
||||||
<div class="row my-5">
|
<!-- <section> begin ============================-->
|
||||||
<div class="card rounded">
|
<section class="pt-5 pb-9 bg-body-emphasis dark__bg-gray-1200 border-top">
|
||||||
<div class="card-header">
|
<div class="row-small mt-3">
|
||||||
<p class="mb-0">{{ header_title|upper }}</p>
|
<div class="d-flex justify-content-between align-items-end mb-4">
|
||||||
</div>
|
<h2 class="mb-0">{% trans 'Bill' %}</h2>
|
||||||
<div class="card-body">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<div class="row">
|
{% if bill.is_draft %}
|
||||||
<div class="col-md-6">
|
<a href="{% url 'in_review_bill' bill.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Review Bill' %}</span></a>
|
||||||
<p>
|
{% endif %}
|
||||||
<strong>{{ _('Account Name') }}:</strong> {{ account.name }}
|
{% if bill.is_review %}
|
||||||
</p>
|
<button id="mark_bill_as_approved" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#mark_as_approved_Modal"><span class="d-none d-sm-inline-block">{% trans 'Mark as Approved' %}</span></button>
|
||||||
<p>
|
{% endif %}
|
||||||
<strong>{{ _('Account Code') }}:</strong> {{ account.code }}
|
{% if bill.is_approved %}
|
||||||
</p>
|
<a href="{% url 'payment_create' bill.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{% trans 'Record Payment' %}</span></a>
|
||||||
</div>
|
{% endif %}
|
||||||
<div class="col-md-6">
|
{% if bill.is_approved %}
|
||||||
<p>
|
<button id="mark_bill_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">{% trans 'Mark as Paid' %}</span></button>
|
||||||
<strong>{{ _('Balance Type') }}:</strong> {{ account.balance_type }}
|
{% endif %}
|
||||||
</p>
|
</div>
|
||||||
<p>
|
</div>
|
||||||
<strong>{{ _('Active') }}:</strong> {{ account.active }}
|
|
||||||
</p>
|
<!-- ============================================-->
|
||||||
</div>
|
<div class="card mb-5">
|
||||||
</div>
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row g-4 g-xl-1 g-xxl-3 justify-content-between">
|
||||||
<div class="col">
|
<div class="col-sm-auto">
|
||||||
<table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75">
|
<div class="d-sm-block d-inline-flex d-md-flex flex-xl-column flex-xxl-row align-items-center align-items-xl-start align-items-xxl-center">
|
||||||
<tr>
|
<div class="d-flex bg-success-subtle rounded flex-center me-3 mb-sm-3 mb-md-0 mb-xl-3 mb-xxl-0" style="width:32px; height:32px"><span class="text-success-dark" data-feather="dollar-sign" style="width:24px; height:24px"></span></div>
|
||||||
<th class="has-text-centered">{{ _('JE Number') }}</th>
|
<div>
|
||||||
<th class="has-text-centered">{{ _('Date') }}</th>
|
<p class="fw-bold mb-1">{% trans 'Paid Amount' %}</p>
|
||||||
<th class="has-text-centered">{{ _('Debit') }}</th>
|
<h4 class="fw-bolder text-nowrap {% if bill.is_paid %}text-success{% endif %}">${{bill.amount_paid}}</h4>
|
||||||
<th class="has-text-centered">{{ _('Credit') }}</th>
|
<h6 class="fw-bolder text-nowrap">Owned <span class="fw-semibold text-nowrap text-success">${{bill.get_amount_open}}</span></h6>
|
||||||
<th class="has-text-centered">{{ _('Description') }}</th>
|
<div class="progress" style="height:17px">
|
||||||
<th class="has-text-centered">{{ _('Unit') }}</th>
|
<div class="progress-bar fw-semibold bg-{% if bill.get_progress_percent < 100 %}secondary{% else %}success{% endif %} rounded-2" role="progressbar" style="width: {{bill.get_progress_percent}}%" aria-valuenow="{{bill.get_progress_percent}}" aria-valuemin="0" aria-valuemax="100">{{bill.get_progress_percent}}%</div>
|
||||||
<th class="has-text-centered">{{ _('Actions') }}</th>
|
</div>
|
||||||
</tr>
|
</div>
|
||||||
|
</div>
|
||||||
{% for tx in account.transactionmodel_set.all %}
|
</div>
|
||||||
<tr class="has-text-centered">
|
{% if 'net' in bill.terms %}
|
||||||
<td>{{ tx.journal_entry.je_number }}</td>
|
<div class="col-sm-auto">
|
||||||
<td>{{ tx.journal_entry.timestamp }}</td>
|
<div class="d-sm-block d-inline-flex d-md-flex flex-xl-column flex-xxl-row align-items-center align-items-xl-start align-items-xxl-center border-start-sm ps-sm-5 border-translucent">
|
||||||
<td>
|
<div class="d-flex bg-primary-subtle rounded flex-center me-3 mb-sm-3 mb-md-0 mb-xl-3 mb-xxl-0" style="width:32px; height:32px"><span class="text-primary-dark" data-feather="layout" style="width:24px; height:24px"></span></div>
|
||||||
{% if tx.tx_type == 'debit' %}
|
<div>
|
||||||
${{ tx.amount }}
|
<p class="fw-bold mb-1"></p>
|
||||||
{% endif %}
|
<div class="fs-9 text-body-secondary fw-semibold mb-0 d-sm-block d-inline-flex d-md-flex flex-xl-column ">
|
||||||
</td>
|
<table>
|
||||||
<td>
|
<tr>
|
||||||
{% if tx.tx_type == 'credit' %}
|
<td>{% trans 'Terms' %}:</td>
|
||||||
${{ tx.amount }}
|
<td><span class="badge rounded bg-success">{{bill.bill_number}}</span></td>
|
||||||
{% endif %}
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
<td>{{ tx.description }}</td>
|
<td>{% trans 'Date Due' %}:</td>
|
||||||
<td>{{ tx.journal_entry.entity_unit.name }}</td>
|
<td><span class="badge rounded bg-success">{{bill.date_due}}</span></td>
|
||||||
<td>
|
</tr>
|
||||||
<div class="btn-reveal-trigger position-static">
|
<tr>
|
||||||
<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>
|
<td>{% trans 'Due in Days' %}:</td>
|
||||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
<td>
|
||||||
<a class="dropdown-item" href="{% url 'payment_details' tx.journal_entry.pk %}">{% trans 'view'|capfirst %}</a>
|
<span class="badge rounded bg-success">{{bill.due_in_days}}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{% trans 'Is Past Due' %}:</td>
|
||||||
|
<td>
|
||||||
|
{% if bill.is_past_due %}
|
||||||
|
<span class="badge rounded bg-danger">{% trans 'Yes' %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge rounded bg-success">{% trans 'No' %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
{% endif %}
|
||||||
{% endfor %}
|
<div class="col-sm-auto">
|
||||||
<tr class="has-text-weight-bold">
|
<div class="d-sm-block d-inline-flex d-md-flex flex-xl-column flex-xxl-row align-items-center align-items-xl-start align-items-xxl-center border-start-sm ps-sm-5 border-translucent">
|
||||||
<td></td>
|
<div class="d-flex bg-primary-subtle rounded flex-center me-3 mb-sm-3 mb-md-0 mb-xl-3 mb-xxl-0" style="width:32px; height:32px"><span class="text-primary-dark" data-feather="layout" style="width:24px; height:24px"></span></div>
|
||||||
<td class="has-text-right">Total</td>
|
<div>
|
||||||
<td class="has-text-centered">${{ total_debits }}</td>
|
<p class="fw-bold mb-1">{% trans 'Due Amount' %}</p>
|
||||||
<td class="has-text-centered">${{ total_credits }}</td>
|
{% if bill.is_paid %}
|
||||||
<td></td>
|
<s><h4 class="fw-bolder text-nowrap">${{bill.amount_due}} </h4></s>
|
||||||
<td></td>
|
{% else %}
|
||||||
<td></td>
|
<h4 class="fw-bolder text-nowrap">${{bill.amount_due}} </h4>
|
||||||
</tr>
|
{% endif %}
|
||||||
</table>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <section> begin ============================-->
|
||||||
|
<div class="bg-body dark__bg-gray-1100 p-4 mb-4 rounded-2 text-body-tertiary">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-12 col-lg-3">
|
||||||
|
<div class="row g-4 g-lg-2">
|
||||||
|
<div class="col-12 col-sm-6 col-lg-12">
|
||||||
|
<div class="row align-items-center g-0">
|
||||||
|
<div class="col-auto col-lg-6 col-xl-5">
|
||||||
|
<h6 class="mb-0 me-3">{% trans "Bill Number" %} :</h6>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto col-lg-6 col-xl-7">
|
||||||
|
<p class="fs-9 text-body-secondary fw-semibold mb-0">#{{bill.bill_number}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-lg-12">
|
||||||
|
<div class="row align-items-center g-0">
|
||||||
|
<div class="col-auto col-lg-6 col-xl-5">
|
||||||
|
<h6 class="me-3">{% trans "Bill Date" %} :</h6>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto col-lg-6 col-xl-7">
|
||||||
|
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{bill.created}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-lg-5">
|
||||||
|
<div class="row align-items-center g-0">
|
||||||
|
<div class="col-auto col-lg-6 col-xl-5">
|
||||||
|
<h6 class="mb-2 me-3">{% trans "Customer Name" %} :</h6>
|
||||||
|
<p class="fs-9 text-body-secondary fw-semibold mb-0">{{bill.vendor.vendor_name}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-lg-4">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-12 col-lg-6">
|
||||||
|
<h6 class="mb-2"> {% trans "bill Status" %} :</h6>
|
||||||
|
<div class="fs-9 text-body-secondary fw-semibold mb-0">
|
||||||
|
{% if bill.bill_status == 'draft' %}
|
||||||
|
<span class="badge text-bg-warning">{% trans "Draft" %}</span>
|
||||||
|
{% elif bill.bill_status == 'in_review' %}
|
||||||
|
<span class="badge text-bg-info">{% trans "In Review" %}</span>
|
||||||
|
{% elif bill.bill_status == 'approved' %}
|
||||||
|
<span class="badge text-bg-info">{% trans "Approved" %}</span>
|
||||||
|
{% elif bill.bill_status == 'declined' %}
|
||||||
|
<span class="badge text-bg-danger">{% trans "Declined" %}</span>
|
||||||
|
{% elif bill.bill_status == 'paid' %}
|
||||||
|
<span class="badge text-bg-success">{% trans "Paid" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-0">
|
||||||
|
<div class="table-responsive scrollbar">
|
||||||
|
<table id="bill-table" class="table fs-9 text-body mb-0">
|
||||||
|
<thead class="bg-body-secondary">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" style="width: 24px;">#</th>
|
||||||
|
<th scope="col" style="min-width: 260px;">{% trans "Item" %}</th>
|
||||||
|
<th scope="col" style="min-width: 60px;">{% trans "Quantity" %}</th>
|
||||||
|
<th scope="col" style="min-width: 60px;">{% trans "Unit Price" %}</th>
|
||||||
|
<th scope="col" style="min-width: 60px;">{% trans "Total" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in car_and_item_info %}
|
||||||
|
<tr>
|
||||||
|
<td class="">{{forloop.counter}}</td>
|
||||||
|
<td class="">{{item.car.id_car_model}}</td>
|
||||||
|
<td class="align-middle">{{item.itemmodel.quantity}}</td>
|
||||||
|
<td class="align-middle ps-5">{{item.car.finances.cost_price}}</td>
|
||||||
|
<td class="align-middle text-body-tertiary fw-semibold">{{item.total}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
<tr class="bg-body-secondary total-sum">
|
||||||
|
<td class="align-middle ps-4 fw-bolder text-body-highlight" colspan="4">{% trans "Grand Total" %}</td>
|
||||||
|
<td class="align-middle text-start fw-bolder">
|
||||||
|
<span id="grand-total">{{grand_total}}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</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 %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
function calculateTotals() {
|
||||||
|
const table = document.getElementById('estimate-table');
|
||||||
|
const rows = table.getElementsByTagName('tbody')[0].rows;
|
||||||
|
let grandTotal = 0;
|
||||||
|
|
||||||
|
for (let row of rows) {
|
||||||
|
// Ensure the row has the expected number of cells
|
||||||
|
if (row.cells.length >= 5) {
|
||||||
|
const quantity = parseFloat(row.cells[2].textContent); // Quantity column
|
||||||
|
const unitPrice = parseFloat(row.cells[3].textContent); // Unit Price column
|
||||||
|
|
||||||
|
if (!isNaN(quantity) && !isNaN(unitPrice)) {
|
||||||
|
const total = quantity * unitPrice;
|
||||||
|
row.cells[4].textContent = total.toFixed(2); // Populate Total column
|
||||||
|
grandTotal += total; // Add to grand total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the grand total
|
||||||
|
document.getElementById('grand-total').textContent = grandTotal.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Run the function on page load
|
||||||
|
window.onload = calculateTotals;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -1,38 +1,159 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
|
||||||
{% load crispy_forms_filters %}
|
{% load crispy_forms_filters %}
|
||||||
{% block title %}{% trans "account" %}{% endblock title %}
|
{% load i18n static %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("Create Bill") }}{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row my-5">
|
<div class="row mt-4">
|
||||||
<!-- Display Form Errors -->
|
<h3 class="text-center">{% trans "Create Bill" %}</h3>
|
||||||
<div class="card shadow rounded">
|
<form id="mainForm" method="post" class="needs-validation">
|
||||||
<div class="card-header bg-primary text-white">
|
{% csrf_token %}
|
||||||
<p class="mb-0">
|
<div class="row g-3">
|
||||||
{% if account.created %}
|
{{ form|crispy }}
|
||||||
<!--<i class="bi bi-pencil-square"></i>-->
|
<div class="row mt-5">
|
||||||
{{ _("Edit Account") }}
|
<div id="formrow">
|
||||||
{% else %}
|
<h3 class="text-start">Unit Items</h3>
|
||||||
<!--<i class="bi bi-person-plus"></i> -->
|
<div class="form-row row g-3 mb-3 mt-5">
|
||||||
{{ _("Add Account") }}
|
<div class="mb-2 col-sm-2">
|
||||||
{% endif %}
|
<select class="form-control item" name="item[]" required>
|
||||||
</p>
|
{% for item in items %}
|
||||||
</div>
|
<option value="{{ item.product.pk }}">{{ item.car.id_car_model }}</option>
|
||||||
<div class="card-body">
|
{% endfor %}
|
||||||
<form method="post" class="form" novalidate>
|
</select>
|
||||||
{% csrf_token %}
|
</div>
|
||||||
{{ form|crispy }}
|
<div class="mb-2 col-sm-2">
|
||||||
{% for error in form.errors %}
|
<input class="form-control quantity" type="number" placeholder="Quantity" name="quantity[]" required>
|
||||||
<div class="text-danger">{{ error }}</div>
|
</div>
|
||||||
{% endfor %}
|
<div class="mb-2 col-sm-1">
|
||||||
<div class="d-flex justify-content-end">
|
<button class="btn btn-danger removeBtn">Remove</button>
|
||||||
<button class="btn btn-sm btn-success me-1" type="submit">
|
</div>
|
||||||
{{ _("Save") }}
|
</div>
|
||||||
</button>
|
|
||||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger">{% trans "Cancel"|capfirst %}</a>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="col-12">
|
||||||
|
<button id="addMoreBtn" class="btn btn-primary">Add More</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<div class="mt-5 text-center">
|
||||||
|
<button type="submit" class="btn btn-success me-2" {% if not items %}disabled{% endif %}>{% trans "Save" %}</button>
|
||||||
|
<a href="{% url 'bill_list' %}" class="btn btn-secondary">{% trans "Cancel" %}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block extra_js %}
|
||||||
|
<script>
|
||||||
|
const Toast = Swal.mixin({
|
||||||
|
toast: true,
|
||||||
|
position: "top-end",
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 2000,
|
||||||
|
timerProgressBar: false,
|
||||||
|
didOpen: (toast) => {
|
||||||
|
toast.onmouseenter = Swal.stopTimer;
|
||||||
|
toast.onmouseleave = Swal.resumeTimer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Add new form fields
|
||||||
|
document.getElementById('addMoreBtn').addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const formrow = document.getElementById('formrow');
|
||||||
|
const newForm = document.createElement('div');
|
||||||
|
newForm.className = 'form-row row g-3 mb-3 mt-5';
|
||||||
|
newForm.innerHTML = `
|
||||||
|
<div class="mb-2 col-sm-2">
|
||||||
|
<select class="form-control item" name="item[]" required>
|
||||||
|
{% for item in items %}
|
||||||
|
<option value="{{ item.product.pk }}">{{ item.car.id_car_model }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2 col-sm-2">
|
||||||
|
<input class="form-control quantity" type="number" placeholder="Quantity" name="quantity[]" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2 col-sm-1">
|
||||||
|
<button class="btn btn-danger removeBtn">Remove</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
formrow.appendChild(newForm);
|
||||||
|
|
||||||
|
// Add remove button functionality
|
||||||
|
newForm.querySelector('.removeBtn').addEventListener('click', function() {
|
||||||
|
newForm.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add remove button functionality to the initial form
|
||||||
|
document.querySelectorAll('.form-row').forEach(row => {
|
||||||
|
row.querySelector('.removeBtn').addEventListener('click', function() {
|
||||||
|
row.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
document.getElementById('mainForm').addEventListener('submit', async function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
/*const titleInput = document.querySelector('[name="title"]');
|
||||||
|
if (titleInput.value.length < 5) {
|
||||||
|
notify("error", "Customer billte Title must be at least 5 characters long.");
|
||||||
|
return; // Stop form submission
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Collect all form data
|
||||||
|
const formData = {
|
||||||
|
csrfmiddlewaretoken: document.querySelector('[name=csrfmiddlewaretoken]').value,
|
||||||
|
vendor: document.querySelector('[name=vendor]').value,
|
||||||
|
xref: document.querySelector('[name=xref]').value,
|
||||||
|
date_draft: document.querySelector('[name=date_draft]').value,
|
||||||
|
terms: document.querySelector('[name=terms]').value,
|
||||||
|
item: [],
|
||||||
|
quantity: []
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Collect multi-value fields (e.g., item[], quantity[])
|
||||||
|
document.querySelectorAll('[name="item[]"]').forEach(input => {
|
||||||
|
formData.item.push(input.value);
|
||||||
|
});
|
||||||
|
document.querySelectorAll('[name="quantity[]"]').forEach(input => {
|
||||||
|
formData.quantity.push(input.value);
|
||||||
|
});
|
||||||
|
console.log(formData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send data to the server using fetch
|
||||||
|
const response = await fetch("{% url 'bill_create' %}", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': formData.csrfmiddlewaretoken,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(formData)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parse the JSON response
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Handle the response
|
||||||
|
if (data.status === "error") {
|
||||||
|
notify("error", data.message); // Display an error message
|
||||||
|
} else if (data.status === "success") {
|
||||||
|
notify("success","Bill created successfully");
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.assign(data.url); // Redirect to the provided URL
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
notify("error","Unexpected response from the server");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
notify("error", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock extra_js %}
|
||||||
@ -30,30 +30,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Customer Table -->
|
<!-- Customer Table -->
|
||||||
|
|
||||||
{% if page_obj.object_list %}
|
|
||||||
<div id="accountsTable">
|
<div id="accountsTable">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-sm fs-9 mb-0">
|
<table class="table table-sm fs-9 mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-body-highlight">
|
<tr class="bg-body-highlight">
|
||||||
<th class="border-top border-translucent ps-3">
|
<th class="border-top border-translucent ps-3">
|
||||||
{% trans 'Account Name' %}
|
{% trans 'Bill Number' %}
|
||||||
</th>
|
</th>
|
||||||
<th class="border-top border-translucent">
|
<th class="border-top border-translucent">
|
||||||
{% trans 'Code' %}
|
{% trans 'Bill Status' %}
|
||||||
</th>
|
</th>
|
||||||
<th class="border-top border-translucent text-end pe-3">
|
<th class="border-top border-translucent text-end pe-3">
|
||||||
{% trans 'Balance Type' %}
|
{% trans 'Vendor' %}
|
||||||
</th>
|
|
||||||
<th class="border-top border-translucent text-end pe-3">
|
|
||||||
{% trans 'Active' %}
|
|
||||||
</th>
|
</th>
|
||||||
<th class="border-top border-translucent text-end align-middle pe-0 ps-4" scope="col"></th>
|
<th class="border-top border-translucent text-end align-middle pe-0 ps-4" scope="col"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="list">
|
<tbody class="list">
|
||||||
{% for bill in bills %}
|
{% 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 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-dialog modal-sm">
|
||||||
@ -78,31 +73,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="align-middle ps-3">{{ bill.name }}</td>
|
<td class="align-middle ps-3">{{ bill.bill_number }}</td>
|
||||||
<td class="align-middle">{{ bill.code }}</td>
|
<td class="align-middle">{{ bill.bill_status }}</td>
|
||||||
<td class="align-middle text-end py-3 pe-3">
|
<td class="align-middle text-end py-3 pe-3">
|
||||||
{% if bill.balance_type == 'debit' %}
|
{{bill.vendor.vendor_name}}
|
||||||
<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>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-reveal-trigger position-static">
|
<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>
|
<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">
|
<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>
|
<a href="{% url 'bill_detail' bill.pk %}" 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 class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -157,8 +137,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
21
templates/ledger/bills/bill_update_form.html
Normal file
21
templates/ledger/bills/bill_update_form.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% block title %}{% trans "Bill" %}{% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="row my-4">
|
||||||
|
<h2>{% trans "Bill" %}</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary">
|
||||||
|
{% if bill.is_draft %}
|
||||||
|
{% trans "Mark As Review" %}
|
||||||
|
{% elif bill.is_review or bill.is_approved %}
|
||||||
|
{% trans "Save" %}
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
<a href="{% url 'bill_detail' pk=bill.pk %}" class="btn btn-sm btn-secondary">{% trans "Cancel" %}</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user