Inoive add update delete messages shown properly

This commit is contained in:
Swapnil9693
2026-03-24 15:51:55 +05:30
parent b78526ad9f
commit 14e799a1d4
4 changed files with 696 additions and 318 deletions

View File

@@ -1,62 +1,271 @@
// Subcontractor autocomplete functionality // $(document).ready(function () {
$(document).ready(function () { // // ===============================
$("#subcontractor").keyup(function () { // // FORM / TABLE TOGGLE
// // ===============================
// if ($('#addForm').length && $('#addTable').length) {
// $('#addForm').show();
// $('#addTable').hide();
// $('#addButton').click(function () {
// $('#addForm').show();
// $('#addTable').hide();
// });
// $('#displayButton').click(function () {
// $('#addForm').hide();
// $('#addTable').show();
// });
// }
// // ===============================
// // Subcontractor autocomplete
// // ===============================
// $("#subcontractor").keyup(function () {
// let query = $(this).val();
// if (query !== "") {
// $.ajax({
// url: "/search_subcontractor",
// method: "POST",
// data: { query: query },
// success: function (data) {
// $("#subcontractor_list").fadeIn().html(data);
// }
// });
// } else {
// $("#subcontractor_list").fadeOut();
// }
// });
// $(document).on("click", "li", function () {
// $("#subcontractor").val($(this).text());
// $("#subcontractor_id").val($(this).attr("data-id"));
// $("#subcontractor_list").fadeOut();
// });
// // Focus
// if (document.getElementById('subcontractor')) {
// document.getElementById('subcontractor').focus();
// }
// // ===============================
// // ADD INVOICE
// // ===============================
// if ($('#invoiceForm').length && window.location.href.includes('add_invoice')) {
// $("#invoiceForm").on("submit", function (e) {
// e.preventDefault();
// let formData = $(this).serialize();
// $.ajax({
// url: '/add_invoice',
// method: 'POST',
// data: formData,
// dataType: 'json',
// success: function (response) {
// if (response.status === "success") {
// alert(response.message || "Invoice added successfully!");
// $('#invoiceForm')[0].reset(); // clear form
// $('#addForm').hide();
// $('#addTable').show(); // switch to table
// location.reload(); // optional refresh
// } else {
// alert(response.message || "Error adding invoice.");
// }
// },
// error: function (xhr) {
// alert(xhr.responseJSON?.message || "Submission failed. Please try again.");
// }
// });
// });
// }
// // Example AJAX update function
// function updateInvoice(invoiceId, formElement) {
// const formData = $(formElement).serialize();
// $.ajax({
// url: '/update_invoice/' + invoiceId,
// method: 'POST',
// data: formData,
// dataType: 'json',
// success: function(response) {
// if(response.status === "success") {
// alert(response.message || "Invoice updated successfully!");
// // ✅ Hide Add Form, Show Table
// $('#addForm').hide();
// $('#addTable').show();
// // Optional: reload table or refresh page
// location.reload();
// } else {
// alert(response.message || "Update failed. Please try again.");
// }
// },
// error: function(xhr) {
// alert(xhr.responseJSON?.message || "Error updating invoice.");
// }
// });
// }
// // ===============================
// // DELETE INVOICE
// // ===============================
// function deleteInvoice(invoiceId, element) {
// if (!confirm("Are you sure you want to delete this invoice?")) return;
// $.ajax({
// url: '/delete_invoice/' + invoiceId,
// method: 'GET',
// dataType: 'json',
// success: function (response) {
// alert(response.message || "Invoice deleted successfully!");
// if (element) $(element).closest("tr").remove();
// },
// error: function (xhr) {
// alert(xhr.responseJSON?.message || "Error deleting invoice. Please try again.");
// }
// });
// }
$(document).ready(function () {
// ===============================
// FORM / TABLE TOGGLE
// ===============================
if ($('#addForm').length && $('#addTable').length) {
// Default: show form, hide table
$('#addForm').show();
$('#addTable').hide();
// ✅ Check URL hash to show table instead
if (window.location.hash === "#addTable") {
$('#addForm').hide();
$('#addTable').show();
}
$('#addButton').click(function () {
$('#addForm').show();
$('#addTable').hide();
});
$('#displayButton').click(function () {
$('#addForm').hide();
$('#addTable').show();
});
}
// ===============================
// Subcontractor autocomplete
// ===============================
$("#subcontractor").keyup(function () {
let query = $(this).val(); let query = $(this).val();
if (query !== "") { if (query !== "") {
$.ajax({ $.ajax({
url: "/search_subcontractor", url: "/search_subcontractor",
method: "POST", method: "POST",
data: { query: query }, data: { query: query },
success: function (data) { success: function (data) {
$("#subcontractor_list").fadeIn().html(data); $("#subcontractor_list").fadeIn().html(data);
} }
}); });
} else { } else {
$("#subcontractor_list").fadeOut(); $("#subcontractor_list").fadeOut();
} }
}); });
$(document).on("click", "li", function () { $(document).on("click", "li", function () {
$("#subcontractor").val($(this).text()); $("#subcontractor").val($(this).text());
$("#subcontractor_id").val($(this).attr("data-id")); $("#subcontractor_id").val($(this).attr("data-id"));
$("#subcontractor_list").fadeOut(); $("#subcontractor_list").fadeOut();
});
}); });
// Success Alert: show alert and reload after 3 seconds // Focus
function showSuccessAlert() { if (document.getElementById('subcontractor')) {
const alertBox = document.getElementById("invoiceSuccessAlert"); document.getElementById('subcontractor').focus();
alertBox.classList.add("show");
setTimeout(() => {
alertBox.classList.remove("show");
// Reload page or redirect after alert hides
window.location.href = '/add_invoice';
}, 3000);
} }
// Submit form via AJAX // ===============================
$("#invoiceForm").on("submit", function (e) { // ADD INVOICE
e.preventDefault(); // ===============================
let formData = $(this).serialize(); if ($('#invoiceForm').length && window.location.href.includes('add_invoice')) {
$.ajax({ $("#invoiceForm").on("submit", function (e) {
url: '/add_invoice', e.preventDefault();
method: 'POST', let formData = $(this).serialize();
data: formData,
success: function (response) {
if(response.status === "success") {
showSuccessAlert();
} else {
alert(response.message);
}
},
error: function (xhr, status, error) {
alert("Submission failed: " + error);
}
});
});
$.ajax({
url: '/add_invoice',
method: 'POST',
data: formData,
dataType: 'json',
success: function (response) {
if (response.status === "success") {
alert(response.message || "Invoice added successfully!");
$('#invoiceForm')[0].reset(); // clear form
$('#addForm').hide();
$('#addTable').show(); // switch to table
location.reload(); // optional refresh
} else {
alert(response.message || "Error adding invoice.");
}
},
error: function (xhr) {
let msg = xhr.responseJSON?.message || "Submission failed. Please try again.";
alert(msg);
}
});
});
}
// ===============================
// UPDATE INVOICE
// ===============================
function updateInvoice(invoiceId, formElement) {
const formData = $(formElement).serialize();
window.onload = function () { $.ajax({
document.getElementById('subcontractor').focus(); url: '/update_invoice/' + invoiceId,
}; method: 'POST',
data: formData,
dataType: 'json',
success: function(response) {
if(response.status === "success") {
alert(response.message || "Invoice updated successfully!");
// Redirect to Add Invoice page's table part
window.location.href = "/add_invoice#addTable";
} else {
alert(response.message || "Update failed. Please try again.");
}
},
error: function(xhr) {
let msg = xhr.responseJSON?.message || "Error updating invoice.";
alert(msg);
}
});
}
window.updateInvoice = updateInvoice; // make globally accessible
// ===============================
// DELETE INVOICE
// ===============================
function deleteInvoice(invoiceId, element) {
if (!confirm("Are you sure you want to delete this invoice?")) return;
$.ajax({
url: '/delete_invoice/' + invoiceId,
method: 'GET',
dataType: 'json',
success: function (response) {
if (response.status === "success") {
alert(response.message || "Invoice deleted successfully!");
if (element) $(element).closest("tr").remove();
} else {
alert(response.message || "Error deleting invoice.");
}
},
error: function (xhr) {
let msg = xhr.responseJSON?.message || "Error deleting invoice. Please try again.";
alert(msg);
}
});
}
window.deleteInvoice = deleteInvoice; // make globally accessible
});

View File

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

View File

@@ -7,6 +7,7 @@
<title>Edit Invoice</title> <title>Edit Invoice</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style1.css') }}"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style1.css') }}">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head> </head>
@@ -62,7 +63,7 @@
<div class="row2"> <div class="row2">
<div> <div>
<label for="invoice_no">Invoice No:</label> <label for="invoice_no">Invoice No:</label>
<input type="text" id="invoice_no" name="invoice_no" value="{{ invoice.Invoice_No }}" required/> <input type="text" id="invoice_no" name="invoice_no" value="{{ invoice.invoice_no }}" required/>
</div> </div>
<div> <div>
<label for="invoice_date">Invoice Date:</label> <label for="invoice_date">Invoice Date:</label>
@@ -180,27 +181,29 @@ $(document).ready(function() {
$(this).closest(".hold-amount-row").remove(); $(this).closest(".hold-amount-row").remove();
}); });
// Submit form via AJAX // Submit form via AJAX
$("#invoiceForm").submit(function(e) { $("#invoiceForm").submit(function(e) {
e.preventDefault(); e.preventDefault();
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $(this).attr("action"), url: $(this).attr("action"),
data: $(this).serialize(), data: $(this).serialize(),
success: function(response) { dataType: 'json', // ensure JSON is returned
if(response.status === "success") { success: function(response) {
$("#invoiceSuccessAlert").fadeIn().delay(3000).fadeOut(); if(response.status === "success") {
alert("Invoice updated successfully!"); // <-- Popup alert alert("Invoice updated successfully!"); // <-- Popup alert
}
}, // ✅ Redirect to Add Invoice page (table part visible)
error: function(xhr) { window.location.href = "{{ url_for('invoice.add_invoice') }}#addTable";
alert("Error: " + xhr.responseJSON.message);
} }
}); },
error: function(xhr) {
alert("Error: " + xhr.responseJSON?.message || "Something went wrong!");
}
}); });
}); });
});
</script> </script>
</body> </body>