370 lines
14 KiB
HTML
370 lines
14 KiB
HTML
|
|
{% extends 'base.html' %}
|
||
|
|
{% block content %}
|
||
|
|
<head xmlns="http://www.w3.org/1999/html">
|
||
|
|
<meta charset="UTF-8"/>
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||
|
|
<title>Add Invoice</title>
|
||
|
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}">
|
||
|
|
<script src="{{ url_for('static', filename='js/invoice.js') }}"></script>
|
||
|
|
<script src="{{ url_for('static', filename='js/holdAmount.js') }}"></script>
|
||
|
|
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
{% if success == 'true' %}
|
||
|
|
<div class="alert alert-success alert-dismissible fade show mt-3" role="alert">
|
||
|
|
✅ Invoice added successfully!
|
||
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||
|
|
</div>
|
||
|
|
{% endif %}
|
||
|
|
|
||
|
|
|
||
|
|
<!-- Flash Messages -->
|
||
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||
|
|
{% if messages %}
|
||
|
|
<div class="flash-messages">
|
||
|
|
{% for category, message in messages %}
|
||
|
|
<div class="alert {{ category }}">{{ message }}</div>
|
||
|
|
{% endfor %}
|
||
|
|
</div>
|
||
|
|
{% endif %}
|
||
|
|
{% endwith %}
|
||
|
|
|
||
|
|
<div class="button-container">
|
||
|
|
<button id="addButton" class="action-button">Add</button>
|
||
|
|
<button id="displayButton" class="action-button">Display</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="addForm" style="display: none;">
|
||
|
|
<h2>Add Invoice</h2>
|
||
|
|
|
||
|
|
<form id="invoiceForm" action="{{ url_for('add_invoice') }}" method="POST">
|
||
|
|
<div class="row1">
|
||
|
|
<div>
|
||
|
|
<label for="subcontractor">Subcontractor Name:</label>
|
||
|
|
<input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/>
|
||
|
|
<input type="hidden" id="subcontractor_id" name="subcontractor_id"/>
|
||
|
|
<div id="subcontractor_list"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row2">
|
||
|
|
<div>
|
||
|
|
<label for="village">Village Name:</label>
|
||
|
|
<select id="village" name="village" required>
|
||
|
|
<option value="">-- Select Village --</option>
|
||
|
|
{% for village in villages %}
|
||
|
|
<option value="{{ village.Village_Name }}">{{ village.Village_Name }}</option>
|
||
|
|
{% endfor %}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="pmc_no">PMC No:</label>
|
||
|
|
<input type="text" id="pmc_no" name="pmc_no" required/>
|
||
|
|
<div id="pmc_no_list" class="autocomplete-list"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row2">
|
||
|
|
<div>
|
||
|
|
<label for="work_type">Work Type:</label>
|
||
|
|
<input type="text" id="work_type" name="work_type" required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="invoice_details">Invoice Details:</label>
|
||
|
|
<textarea id="invoice_details" name="invoice_details" required></textarea>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row2">
|
||
|
|
<div>
|
||
|
|
<label for="invoice_no">Invoice No:</label>
|
||
|
|
<input type="text" id="invoice_no" name="invoice_no" required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="invoice_date">Invoice Date:</label>
|
||
|
|
<input type="date" id="invoice_date" name="invoice_date" required/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row3">
|
||
|
|
<div>
|
||
|
|
<label for="basic_amount">Basic Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="basic_amount" name="basic_amount" placeholder="₹ - 00.00" required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="debit_amount">Debit Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="debit_amount" name="debit_amount" placeholder="₹ - 00.00" required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="after_debit_amount">After Debit Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="after_debit_amount" name="after_debit_amount" placeholder="₹ - 00.00" readonly required/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row3">
|
||
|
|
<div class="percentage-field">
|
||
|
|
<label for="gst_percentage">GST %:</label>
|
||
|
|
<input type="number" step="0.01" id="gst_percentage" name="gst_percentage" placeholder="%"/>
|
||
|
|
<label for="gst_amount">GST Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="gst_amount" name="gst_amount" placeholder="₹ - 00.00" readonly required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="amount">Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="amount" name="amount" placeholder="₹ - 00.00" readonly required/>
|
||
|
|
</div>
|
||
|
|
<div class="percentage-field">
|
||
|
|
<label for="tds_percentage">TDS %:</label>
|
||
|
|
<input type="number" step="0.01" id="tds_percentage" name="tds_percentage" placeholder="%"/>
|
||
|
|
<label for="tds_amount">TDS Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="tds_amount" name="tds_amount" placeholder="₹ - 00.00" readonly required/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row3">
|
||
|
|
<div class="percentage-field">
|
||
|
|
<label for="sd_percentage">SD %:</label>
|
||
|
|
<input type="number" step="0.01" id="sd_percentage" name="sd_percentage" placeholder="%"/>
|
||
|
|
<label for="sd_amount">SD Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="sd_amount" name="sd_amount" placeholder="₹ - 00.00" readonly required>
|
||
|
|
</div>
|
||
|
|
<div class="percentage-field">
|
||
|
|
<label for="commission_percentage">On Commission %:</label>
|
||
|
|
<input type="number" step="0.01" id="commission_percentage" name="commission_percentage" placeholder="%"/>
|
||
|
|
<label for="on_commission">On Commission:</label>
|
||
|
|
<input type="number" step="0.01" id="on_commission" name="on_commission" placeholder="₹ - 00.00" readonly required>
|
||
|
|
</div>
|
||
|
|
<div class="percentage-field">
|
||
|
|
<label for="hydro_percentage">Hydro Testing %:</label>
|
||
|
|
<input type="number" step="0.01" id="hydro_percentage" name="hydro_percentage" placeholder="%"/>
|
||
|
|
<label for="hydro_testing">Hydro Testing:</label>
|
||
|
|
<input type="number" step="0.01" id="hydro_testing" name="hydro_testing" placeholder="₹ - 00.00" readonly required>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="hold-row">
|
||
|
|
<button type="button" id="add_hold_amount" class="button">+ Add Hold Amount</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Dynamically added hold amount fields -->
|
||
|
|
<div id="hold_amount_container"></div>
|
||
|
|
|
||
|
|
<div class="row2">
|
||
|
|
<div>
|
||
|
|
<label for="gst_sd_amount">GST SD Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="gst_sd_amount" name="gst_sd_amount" placeholder="₹ - 00.00" required/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="final_amount">Final Amount:</label>
|
||
|
|
<input type="number" step="0.01" id="final_amount" name="final_amount" placeholder="₹ - 00.00" required/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<button type="submit" class="button">Submit</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="addTable" style="display: none;">
|
||
|
|
<!-- Invoice Table Section -->
|
||
|
|
<div class="search-container">
|
||
|
|
<h2>Invoice List</h2>
|
||
|
|
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
|
||
|
|
{% if invoices %}
|
||
|
|
<table class="invoice-table">
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Invoice Id</th>
|
||
|
|
<th>SubContractor Name</th>
|
||
|
|
<th>PMC No</th>
|
||
|
|
<th>Village</th>
|
||
|
|
<th>Work Type</th>
|
||
|
|
<th>Invoice Details</th>
|
||
|
|
<th>Invoice Date</th>
|
||
|
|
<th>Invoice No</th>
|
||
|
|
<th>Basic Amount</th>
|
||
|
|
<th>Debit Amount</th>
|
||
|
|
<th>After Debit Amount</th>
|
||
|
|
<th>Amount</th>
|
||
|
|
<th>GST Amount</th>
|
||
|
|
<th>TDS Amount</th>
|
||
|
|
<th>SD Amount</th>
|
||
|
|
<th>On Commission</th>
|
||
|
|
<th>Hydro Testing</th>
|
||
|
|
<th>GST SD Amount</th>
|
||
|
|
<th>Final Amount</th>
|
||
|
|
<th>Update</th>
|
||
|
|
<th>Delete</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{% for invoice in invoices %}
|
||
|
|
<tr>
|
||
|
|
<td>{{ invoice.Invoice_Id }}</td>
|
||
|
|
<td>{{ invoice.Contractor_Name }}</td>
|
||
|
|
<td>{{ invoice.PMC_No }}</td>
|
||
|
|
<td>{{ invoice.Village_Name or 'N/A' }}</td>
|
||
|
|
<td>{{ invoice.Work_Type }}</td>
|
||
|
|
<td>{{ invoice.Invoice_Details }}</td>
|
||
|
|
<td>{{ invoice.Invoice_Date }}</td>
|
||
|
|
<td>{{ invoice.Invoice_No }}</td>
|
||
|
|
<td>{{ invoice.Basic_Amount }}</td>
|
||
|
|
<td>{{ invoice.Debit_Amount }}</td>
|
||
|
|
<td>{{ invoice.After_Debit_Amount }}</td>
|
||
|
|
<td>{{ invoice.Amount }}</td>
|
||
|
|
<td>{{ invoice.GST_Amount }}</td>
|
||
|
|
<td>{{ invoice.TDS_Amount }}</td>
|
||
|
|
<td>{{ invoice.SD_Amount }}</td>
|
||
|
|
<td>{{ invoice.On_Commission }}</td>
|
||
|
|
<td>{{ invoice.Hydro_Testing }}</td>
|
||
|
|
<td>{{ invoice.GST_SD_Amount }}</td>
|
||
|
|
<td>{{ invoice.Final_Amount }}</td>
|
||
|
|
<td>
|
||
|
|
<a href="{{ url_for('edit_invoice', invoice_id=invoice.Invoice_Id) }}">
|
||
|
|
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit" class="icon">
|
||
|
|
</a>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<a href="{{ url_for('delete_invoice', invoice_id=invoice.Invoice_Id) }}"
|
||
|
|
onclick="return confirm('Are you sure?')">
|
||
|
|
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete" class="icon">
|
||
|
|
</a>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
{% endfor %}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
{% else %}
|
||
|
|
<p>No invoices found.</p>
|
||
|
|
{% endif %}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
||
|
|
// Get all the input fields
|
||
|
|
const basicAmount = document.getElementById('basic_amount');
|
||
|
|
const debitAmount = document.getElementById('debit_amount');
|
||
|
|
const afterDebitAmount = document.getElementById('after_debit_amount');
|
||
|
|
const amount = document.getElementById('amount');
|
||
|
|
|
||
|
|
// Percentage fields
|
||
|
|
const gstPercentage = document.getElementById('gst_percentage');
|
||
|
|
const gstAmount = document.getElementById('gst_amount');
|
||
|
|
const tdsPercentage = document.getElementById('tds_percentage');
|
||
|
|
const tdsAmount = document.getElementById('tds_amount');
|
||
|
|
const sdPercentage = document.getElementById('sd_percentage');
|
||
|
|
const sdAmountInput = document.getElementById('sd_amount');
|
||
|
|
const commissionPercentage = document.getElementById('commission_percentage');
|
||
|
|
const onCommission = document.getElementById('on_commission');
|
||
|
|
const hydroPercentage = document.getElementById('hydro_percentage');
|
||
|
|
const hydroTesting = document.getElementById('hydro_testing');
|
||
|
|
const gstSdAmount = document.getElementById('gst_sd_amount');
|
||
|
|
const finalAmount = document.getElementById('final_amount');
|
||
|
|
|
||
|
|
// Calculate after debit amount when basic or debit amount changes
|
||
|
|
function calculateAfterDebitAmount() {
|
||
|
|
const basic = parseFloat(basicAmount.value) || 0;
|
||
|
|
const debit = parseFloat(debitAmount.value) || 0;
|
||
|
|
const afterDebit = basic - debit;
|
||
|
|
afterDebitAmount.value = afterDebit.toFixed(2);
|
||
|
|
calculateGST();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate GST and Amount
|
||
|
|
function calculateGST() {
|
||
|
|
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
||
|
|
|
||
|
|
if (gstPercentage.value) {
|
||
|
|
const gstPerc = parseFloat(gstPercentage.value) || 0;
|
||
|
|
const gstAmt = (baseAmount * gstPerc) / 100;
|
||
|
|
gstAmount.value = gstAmt.toFixed(2);
|
||
|
|
gstSdAmount.value = gstAmt.toFixed(2);
|
||
|
|
|
||
|
|
// Calculate Amount (After Debit + GST)
|
||
|
|
amount.value = (baseAmount + gstAmt).toFixed(2);
|
||
|
|
} else {
|
||
|
|
amount.value = baseAmount.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
calculateOtherDeductions();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate other deductions (TDS, SD, Commission, Hydro)
|
||
|
|
function calculateOtherDeductions() {
|
||
|
|
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
||
|
|
|
||
|
|
// Calculate TDS
|
||
|
|
if (tdsPercentage.value) {
|
||
|
|
const tdsPerc = parseFloat(tdsPercentage.value) || 0;
|
||
|
|
const tdsAmt = (baseAmount * tdsPerc) / 100;
|
||
|
|
tdsAmount.value = tdsAmt.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate SD
|
||
|
|
if (sdPercentage.value) {
|
||
|
|
const sdPerc = parseFloat(sdPercentage.value) || 0;
|
||
|
|
const sdAmt = (baseAmount * sdPerc) / 100;
|
||
|
|
sdAmountInput.value = sdAmt.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate Commission
|
||
|
|
if (commissionPercentage.value) {
|
||
|
|
const commPerc = parseFloat(commissionPercentage.value) || 0;
|
||
|
|
const commAmt = (baseAmount * commPerc) / 100;
|
||
|
|
onCommission.value = commAmt.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate Hydro Testing
|
||
|
|
if (hydroPercentage.value) {
|
||
|
|
const hydroPerc = parseFloat(hydroPercentage.value) || 0;
|
||
|
|
const hydroAmt = (baseAmount * hydroPerc) / 100;
|
||
|
|
hydroTesting.value = hydroAmt.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
calculateFinalAmount();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate final amount
|
||
|
|
function calculateFinalAmount() {
|
||
|
|
const amt = parseFloat(amount.value) || 0;
|
||
|
|
const tds = parseFloat(tdsAmount.value) || 0;
|
||
|
|
const sd = parseFloat(sdAmountInput.value) || 0;
|
||
|
|
const commission = parseFloat(onCommission.value) || 0;
|
||
|
|
const hydro = parseFloat(hydroTesting.value) || 0;
|
||
|
|
const gstSd = parseFloat(gstSdAmount.value) || 0;
|
||
|
|
|
||
|
|
// Get hold amounts
|
||
|
|
let totalHold = 0;
|
||
|
|
document.querySelectorAll('input[name="hold_amount[]"]').forEach(input => {
|
||
|
|
totalHold += parseFloat(input.value) || 0;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Final Amount = Amount - TDS - SD - Commission - Hydro - GST SD - Hold Amounts
|
||
|
|
const final = amt - tds - sd - commission - hydro - gstSd - totalHold;
|
||
|
|
finalAmount.value = final.toFixed(2);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add event listeners
|
||
|
|
basicAmount.addEventListener('input', calculateAfterDebitAmount);
|
||
|
|
debitAmount.addEventListener('input', calculateAfterDebitAmount);
|
||
|
|
|
||
|
|
// Percentage fields
|
||
|
|
gstPercentage.addEventListener('input', calculateGST);
|
||
|
|
tdsPercentage.addEventListener('input', calculateOtherDeductions);
|
||
|
|
sdPercentage.addEventListener('input', calculateOtherDeductions);
|
||
|
|
commissionPercentage.addEventListener('input', calculateOtherDeductions);
|
||
|
|
hydroPercentage.addEventListener('input', calculateOtherDeductions);
|
||
|
|
|
||
|
|
// Listen for changes in hold amounts
|
||
|
|
document.addEventListener('holdAmountChanged', calculateFinalAmount);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Optional JS for auto-hiding flash
|
||
|
|
setTimeout(() => {
|
||
|
|
document.querySelectorAll('.alert').forEach(el => el.style.display = 'none');
|
||
|
|
}, 5000);
|
||
|
|
</script>
|
||
|
|
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</body>
|
||
|
|
|
||
|
|
{% endblock %}
|