diff --git a/__pycache__/config.cpython-314.pyc b/__pycache__/config.cpython-314.pyc index f7ac19f..847ed1a 100644 Binary files a/__pycache__/config.cpython-314.pyc and b/__pycache__/config.cpython-314.pyc differ diff --git a/controllers/__pycache__/auth_controller.cpython-314.pyc b/controllers/__pycache__/auth_controller.cpython-314.pyc index 7cb6550..3a95e79 100644 Binary files a/controllers/__pycache__/auth_controller.cpython-314.pyc and b/controllers/__pycache__/auth_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/block_controller.cpython-314.pyc b/controllers/__pycache__/block_controller.cpython-314.pyc index 6b94898..cd3b3a2 100644 Binary files a/controllers/__pycache__/block_controller.cpython-314.pyc and b/controllers/__pycache__/block_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/district_controller.cpython-314.pyc b/controllers/__pycache__/district_controller.cpython-314.pyc index a85b069..7cfd7d7 100644 Binary files a/controllers/__pycache__/district_controller.cpython-314.pyc and b/controllers/__pycache__/district_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/excel_upload_controller.cpython-314.pyc b/controllers/__pycache__/excel_upload_controller.cpython-314.pyc index a30548e..2b6e062 100644 Binary files a/controllers/__pycache__/excel_upload_controller.cpython-314.pyc and b/controllers/__pycache__/excel_upload_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/gst_release_controller.cpython-314.pyc b/controllers/__pycache__/gst_release_controller.cpython-314.pyc index ff435e4..ecb0aee 100644 Binary files a/controllers/__pycache__/gst_release_controller.cpython-314.pyc and b/controllers/__pycache__/gst_release_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/hold_types_controller.cpython-314.pyc b/controllers/__pycache__/hold_types_controller.cpython-314.pyc index f9eb4d1..1835d4c 100644 Binary files a/controllers/__pycache__/hold_types_controller.cpython-314.pyc and b/controllers/__pycache__/hold_types_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/invoice_controller.cpython-314.pyc b/controllers/__pycache__/invoice_controller.cpython-314.pyc index 6bfc202..e14f3b9 100644 Binary files a/controllers/__pycache__/invoice_controller.cpython-314.pyc and b/controllers/__pycache__/invoice_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/log_controller.cpython-314.pyc b/controllers/__pycache__/log_controller.cpython-314.pyc index 0e24c26..2c624d3 100644 Binary files a/controllers/__pycache__/log_controller.cpython-314.pyc and b/controllers/__pycache__/log_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/payment_controller.cpython-314.pyc b/controllers/__pycache__/payment_controller.cpython-314.pyc index c942139..416f0a1 100644 Binary files a/controllers/__pycache__/payment_controller.cpython-314.pyc and b/controllers/__pycache__/payment_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/pmc_report_controller.cpython-314.pyc b/controllers/__pycache__/pmc_report_controller.cpython-314.pyc index 76b3ae2..7ba9e43 100644 Binary files a/controllers/__pycache__/pmc_report_controller.cpython-314.pyc and b/controllers/__pycache__/pmc_report_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/report_controller.cpython-314.pyc b/controllers/__pycache__/report_controller.cpython-314.pyc index bc846ee..fbf06a1 100644 Binary files a/controllers/__pycache__/report_controller.cpython-314.pyc and b/controllers/__pycache__/report_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/state_controller.cpython-314.pyc b/controllers/__pycache__/state_controller.cpython-314.pyc index ba9b5ce..f6bd2c1 100644 Binary files a/controllers/__pycache__/state_controller.cpython-314.pyc and b/controllers/__pycache__/state_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/subcontractor_controller.cpython-314.pyc b/controllers/__pycache__/subcontractor_controller.cpython-314.pyc index 8f6332d..d431fc7 100644 Binary files a/controllers/__pycache__/subcontractor_controller.cpython-314.pyc and b/controllers/__pycache__/subcontractor_controller.cpython-314.pyc differ diff --git a/controllers/__pycache__/village_controller.cpython-314.pyc b/controllers/__pycache__/village_controller.cpython-314.pyc index 888646e..d00d6b1 100644 Binary files a/controllers/__pycache__/village_controller.cpython-314.pyc and b/controllers/__pycache__/village_controller.cpython-314.pyc differ diff --git a/controllers/gst_release_controller.py b/controllers/gst_release_controller.py index 009372c..5827f8a 100644 --- a/controllers/gst_release_controller.py +++ b/controllers/gst_release_controller.py @@ -1,8 +1,8 @@ -from flask import Blueprint, render_template, request, redirect, url_for +# routes/gst_release_routes.py +from flask import Blueprint, render_template, request, redirect, url_for, flash from flask_login import login_required from model.gst_release import GSTRelease from model.Log import LogHelper -from flask import flash, current_app gst_release_bp = Blueprint('gst_release_bp', __name__) gst_service = GSTRelease() @@ -13,7 +13,7 @@ gst_service = GSTRelease() def add_gst_release(): if request.method == 'POST': gst_service.AddGSTRelease(request) - LogHelper.log_action("Add GST Release", f"User added GST release") + LogHelper.log_action("Add GST Release", "User added GST release") flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error') return redirect(url_for('gst_release_bp.add_gst_release')) @@ -30,7 +30,7 @@ def edit_gst_release(gst_release_id): if request.method == 'POST': gst_service.EditGSTRelease(request, gst_release_id) - LogHelper.log_action("Edit GST Release", f"User edited GST release") + LogHelper.log_action("Edit GST Release", "User edited GST release") flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error') return redirect(url_for('gst_release_bp.add_gst_release')) @@ -40,7 +40,7 @@ def edit_gst_release(gst_release_id): @gst_release_bp.route('/delete_gst_release/', methods=['GET', 'POST']) @login_required def delete_gst_release(gst_release_id): - gst_service.DeleteGSTRelease(gst_release_id) # remove request - LogHelper.log_action("Delete GST Release", f"User deleted GST release") + gst_service.DeleteGSTRelease(gst_release_id) + LogHelper.log_action("Delete GST Release", "User deleted GST release") flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error') return redirect(url_for('gst_release_bp.add_gst_release')) \ No newline at end of file diff --git a/model/Invoice.py b/model/Invoice.py index b002fb3..d82bd0d 100644 --- a/model/Invoice.py +++ b/model/Invoice.py @@ -66,7 +66,7 @@ def get_all_villages(): return fetch_all(cursor) return execute_db_operation(operation) - + # ------------------- Invoice Functions ------------------- def insert_invoice(data, village_id): def operation(cursor): diff --git a/model/ItemCRUD.py b/model/ItemCRUD.py index 59d7469..3f2c656 100644 --- a/model/ItemCRUD.py +++ b/model/ItemCRUD.py @@ -6,7 +6,6 @@ import config import re import mysql.connector - # ---------------------------------------------------------- # Mapping Class # ---------------------------------------------------------- @@ -23,10 +22,11 @@ class itemCRUDMapping: self.name = "Hold Type" elif itemType is ItemCRUDType.Subcontractor: self.name = "Subcontractor" + elif itemType.name == "GSTRelease": + self.name = "GSTRelease" else: self.name = "Item" - # ---------------------------------------------------------- # Generic CRUD Class # ---------------------------------------------------------- @@ -93,13 +93,47 @@ class ItemCRUD: try: # ====================================================== - # SUBCONTRACTOR (MULTI-FIELD) + # GSTRelease MULTI-FIELD # ====================================================== - if data: + if self.itemCRUDType.name == "GSTRelease" and data: + + # Duplicate check (PMC_No + Invoice_No) + if storedprocfetch: + cursor.callproc(storedprocfetch, (data['PMC_No'], data['Invoice_No'])) + existing_item = None + for rs in cursor.stored_results(): + existing_item = rs.fetchone() + if existing_item: + self.isSuccess = False + self.resultMessage = HtmlHelper.json_response( + ResponseHandler.already_exists(self.itemCRUDMapping.name), 409 + ) + return + + # Insert GSTRelease + cursor.callproc(storedprocadd, ( + data['PMC_No'], + data['Invoice_No'], + data['Basic_Amount'], + data['Final_Amount'], + data['Total_Amount'], + data['UTR'], + data['Contractor_ID'] + )) + connection.commit() + + self.isSuccess = True + self.resultMessage = HtmlHelper.json_response( + ResponseHandler.add_success(self.itemCRUDMapping.name), 200 + ) + return + + # ====================================================== + # SUBCONTRACTOR MULTI-FIELD + # ====================================================== + if self.itemCRUDType.name == "Subcontractor" and data: - # Duplicate check cursor.callproc(storedprocfetch, (data['Contractor_Name'],)) - existing_item = None for rs in cursor.stored_results(): existing_item = rs.fetchone() @@ -111,7 +145,6 @@ class ItemCRUD: ) return - # Insert cursor.callproc(storedprocadd, ( data['Contractor_Name'], data['Address'], @@ -123,17 +156,16 @@ class ItemCRUD: data['GST_No'], data['Contractor_password'] )) - connection.commit() - self.isSuccess = True self.resultMessage = HtmlHelper.json_response( ResponseHandler.add_success(self.itemCRUDMapping.name), 200 ) return + # ====================================================== - # NORMAL (Village / Block / State) + # NORMAL SINGLE-FIELD (Village / Block / State) # ====================================================== if not re.match(RegEx.allPattern, childname): self.isSuccess = False @@ -142,7 +174,6 @@ class ItemCRUD: ) return - # Duplicate check if parentid is None: cursor.callproc(storedprocfetch, (childname,)) else: @@ -159,17 +190,14 @@ class ItemCRUD: ) return - # Insert if parentid is None: cursor.callproc(storedprocadd, (childname,)) else: cursor.callproc(storedprocadd, (childname, parentid)) connection.commit() - self.isSuccess = True self.resultMessage = HtmlHelper.json_response( - ResponseHandler.add_success(self.itemCRUDMapping.name), 200 ) @@ -199,9 +227,33 @@ class ItemCRUD: try: # ====================================================== - # SUBCONTRACTOR (MULTI-FIELD) + # GSTRelease MULTI-FIELD # ====================================================== - if data: + if self.itemCRUDType.name == "GSTRelease" and data: + + cursor.callproc(storedprocupdate, ( + childid, + data['PMC_No'], + data['Invoice_No'], + data['Basic_Amount'], + data['Final_Amount'], + data['Total_Amount'], + data['UTR'], + data['Contractor_ID'] + )) + connection.commit() + + self.isSuccess = True + self.resultMessage = HtmlHelper.json_response( + ResponseHandler.update_success(self.itemCRUDMapping.name), 200 + ) + return + + # ====================================================== + # SUBCONTRACTOR MULTI-FIELD + # ====================================================== + if self.itemCRUDType.name == "Subcontractor" and data: + cursor.callproc(storedprocupdate, ( childid, data['Contractor_Name'], @@ -214,9 +266,7 @@ class ItemCRUD: data['GST_No'], data['Contractor_password'] )) - connection.commit() - self.isSuccess = True self.resultMessage = HtmlHelper.json_response( ResponseHandler.update_success(self.itemCRUDMapping.name), 200 @@ -224,7 +274,7 @@ class ItemCRUD: return # ====================================================== - # NORMAL + # NORMAL SINGLE-FIELD # ====================================================== if not re.match(RegEx.allPattern, childname): self.isSuccess = False @@ -237,7 +287,6 @@ class ItemCRUD: cursor.callproc(storedprocupdate, (childid, parentid, childname)) connection.commit() - self.isSuccess = True self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message'] @@ -259,20 +308,15 @@ class ItemCRUD: data = [] connection = config.get_db_connection() - if not connection: return [] cursor = connection.cursor() - try: cursor.callproc(storedproc) - for result in cursor.stored_results(): data = result.fetchall() - self.isSuccess = True - except mysql.connector.Error as e: print(f"Error fetching {self.itemCRUDMapping.name}: {e}") self.isSuccess = False @@ -280,7 +324,6 @@ class ItemCRUD: ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500 ) return [] - finally: cursor.close() connection.close() @@ -298,13 +341,10 @@ class ItemCRUD: try: cursor.callproc(storedproc, (id,)) - for rs in cursor.stored_results(): data = rs.fetchone() - except mysql.connector.Error as e: print(f"Error fetching {self.itemCRUDMapping.name}: {e}") - finally: cursor.close() connection.close() @@ -353,7 +393,6 @@ class ItemCRUD: return HtmlHelper.json_response( ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500 ) - finally: cursor.close() connection.close() \ No newline at end of file diff --git a/model/Utilities.py b/model/Utilities.py index a96e800..4bc4262 100644 --- a/model/Utilities.py +++ b/model/Utilities.py @@ -8,7 +8,7 @@ class ItemCRUDType(Enum): State = 4 HoldType = 5 Subcontractor = 6 - + GSTRelease = 7 class RegEx: patternAlphabetOnly = "^[A-Za-z ]+$" diff --git a/model/__pycache__/Auth.cpython-314.pyc b/model/__pycache__/Auth.cpython-314.pyc index d9bfd24..6b10b20 100644 Binary files a/model/__pycache__/Auth.cpython-314.pyc and b/model/__pycache__/Auth.cpython-314.pyc differ diff --git a/model/__pycache__/Block.cpython-314.pyc b/model/__pycache__/Block.cpython-314.pyc index 77bf401..0052c36 100644 Binary files a/model/__pycache__/Block.cpython-314.pyc and b/model/__pycache__/Block.cpython-314.pyc differ diff --git a/model/__pycache__/District.cpython-314.pyc b/model/__pycache__/District.cpython-314.pyc index d77e609..d0f570a 100644 Binary files a/model/__pycache__/District.cpython-314.pyc and b/model/__pycache__/District.cpython-314.pyc differ diff --git a/model/__pycache__/GST.cpython-314.pyc b/model/__pycache__/GST.cpython-314.pyc index 5f258d6..9cca544 100644 Binary files a/model/__pycache__/GST.cpython-314.pyc and b/model/__pycache__/GST.cpython-314.pyc differ diff --git a/model/__pycache__/HoldTypes.cpython-314.pyc b/model/__pycache__/HoldTypes.cpython-314.pyc index 3a51958..2aa01da 100644 Binary files a/model/__pycache__/HoldTypes.cpython-314.pyc and b/model/__pycache__/HoldTypes.cpython-314.pyc differ diff --git a/model/__pycache__/Invoice.cpython-314.pyc b/model/__pycache__/Invoice.cpython-314.pyc index 68c9058..47bdb00 100644 Binary files a/model/__pycache__/Invoice.cpython-314.pyc and b/model/__pycache__/Invoice.cpython-314.pyc differ diff --git a/model/__pycache__/ItemCRUD.cpython-314.pyc b/model/__pycache__/ItemCRUD.cpython-314.pyc index df8d535..2c87bfc 100644 Binary files a/model/__pycache__/ItemCRUD.cpython-314.pyc and b/model/__pycache__/ItemCRUD.cpython-314.pyc differ diff --git a/model/__pycache__/Log.cpython-314.pyc b/model/__pycache__/Log.cpython-314.pyc index 4c5491b..d772fb9 100644 Binary files a/model/__pycache__/Log.cpython-314.pyc and b/model/__pycache__/Log.cpython-314.pyc differ diff --git a/model/__pycache__/PmcReport.cpython-314.pyc b/model/__pycache__/PmcReport.cpython-314.pyc index 40f23be..7d41e19 100644 Binary files a/model/__pycache__/PmcReport.cpython-314.pyc and b/model/__pycache__/PmcReport.cpython-314.pyc differ diff --git a/model/__pycache__/Report.cpython-314.pyc b/model/__pycache__/Report.cpython-314.pyc index 51dc322..fed9132 100644 Binary files a/model/__pycache__/Report.cpython-314.pyc and b/model/__pycache__/Report.cpython-314.pyc differ diff --git a/model/__pycache__/State.cpython-314.pyc b/model/__pycache__/State.cpython-314.pyc index 7e0b85e..9af47ac 100644 Binary files a/model/__pycache__/State.cpython-314.pyc and b/model/__pycache__/State.cpython-314.pyc differ diff --git a/model/__pycache__/Subcontractor.cpython-314.pyc b/model/__pycache__/Subcontractor.cpython-314.pyc index 838bcdf..9fc5e3d 100644 Binary files a/model/__pycache__/Subcontractor.cpython-314.pyc and b/model/__pycache__/Subcontractor.cpython-314.pyc differ diff --git a/model/__pycache__/Utilities.cpython-314.pyc b/model/__pycache__/Utilities.cpython-314.pyc index d4ac339..2fbbe57 100644 Binary files a/model/__pycache__/Utilities.cpython-314.pyc and b/model/__pycache__/Utilities.cpython-314.pyc differ diff --git a/model/__pycache__/Village.cpython-314.pyc b/model/__pycache__/Village.cpython-314.pyc index dd3c537..60c9c33 100644 Binary files a/model/__pycache__/Village.cpython-314.pyc and b/model/__pycache__/Village.cpython-314.pyc differ diff --git a/model/__pycache__/gst_release.cpython-314.pyc b/model/__pycache__/gst_release.cpython-314.pyc index 69aa90d..1c12e24 100644 Binary files a/model/__pycache__/gst_release.cpython-314.pyc and b/model/__pycache__/gst_release.cpython-314.pyc differ diff --git a/model/__pycache__/payment.cpython-314.pyc b/model/__pycache__/payment.cpython-314.pyc index 9792ad9..14ea8c3 100644 Binary files a/model/__pycache__/payment.cpython-314.pyc and b/model/__pycache__/payment.cpython-314.pyc differ diff --git a/model/gst_release.py b/model/gst_release.py index 7f6985f..c30b08c 100644 --- a/model/gst_release.py +++ b/model/gst_release.py @@ -1,109 +1,8 @@ -# from flask import request -# from model.ItemCRUD import ItemCRUD -# from model.Utilities import ItemCRUDType - -# class GSTRelease: -# """CRUD operations for GST Release using ItemCRUD""" - -# def __init__(self): -# self.isSuccess = False -# self.resultMessage = "" - -# # ------------------- Add GST Release ------------------- -# def AddGSTRelease(self, request): -# pmc_no = request.form.get('PMC_No', '').strip() -# invoice_no = request.form.get('invoice_No', '').strip() - -# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) -# gst.AddItem( -# request=request, -# parentid=None, -# childname=f"{pmc_no}-{invoice_no}", -# storedprocfetch="CheckGSTReleaseExists", -# storedprocadd="AddGSTReleaseFromExcel" # your stored procedure handles extra fields -# ) - -# self.isSuccess = gst.isSuccess -# self.resultMessage = str(gst.resultMessage) - -# # ------------------- Get All GST Releases ------------------- -# def GetAllGSTReleases(self): -# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) -# # Pass request=None for fetch -# rows = gst.GetAllData(request=None, storedproc="GetAllGSTReleases") - -# self.isSuccess = gst.isSuccess -# self.resultMessage = str(gst.resultMessage) - -# data = [] -# for row in rows: -# data.append({ -# "gst_release_id": row[0], -# "pmc_no": row[1], -# "invoice_no": row[2], -# "basic_amount": row[3], -# "final_amount": row[4], -# "total_amount": row[5], -# "utr": row[6], -# "contractor_id": row[7] -# }) -# return data - -# # ------------------- Get GST Release By ID ------------------- -# def GetGSTReleaseByID(self, gst_release_id): -# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) -# row = gst.GetDataByID(gst_release_id, request=None, storedproc="GetGSTReleaseById") - -# self.isSuccess = gst.isSuccess -# self.resultMessage = str(gst.resultMessage) - -# if row: -# return { -# "gst_release_id": row[0], -# "pmc_no": row[1], -# "invoice_no": row[2], -# "basic_amount": row[3], -# "final_amount": row[4], -# "total_amount": row[5], -# "utr": row[6], -# "contractor_id": row[7] -# } -# return None - -# # ------------------- Edit GST Release ------------------- -# def EditGSTRelease(self, request, gst_release_id): -# pmc_no = request.form.get('PMC_No', '').strip() -# invoice_no = request.form.get('invoice_No', '').strip() - -# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) -# gst.EditItem( -# request=request, -# childid=gst_release_id, -# parentid=None, -# childname=f"{pmc_no}-{invoice_no}", -# storedprocupdate="UpdateGSTRelease" # stored procedure handles extra fields -# ) - -# self.isSuccess = gst.isSuccess -# self.resultMessage = str(gst.resultMessage) - -# # ------------------- Delete GST Release ------------------- -# def DeleteGSTRelease(self, gst_release_id): -# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) -# gst.DeleteItem( -# itemID=gst_release_id, -# request=None, -# storedprocDelete="DeleteGSTReleaseById" -# ) - -# self.isSuccess = gst.isSuccess -# self.resultMessage = str(gst.resultMessage) - +# model/gst_release.py from flask import request, jsonify from model.ItemCRUD import ItemCRUD from model.Utilities import ItemCRUDType - class GSTRelease: def __init__(self): @@ -125,12 +24,19 @@ class GSTRelease: "Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0) } + # Add GST Release gst.AddItem( request=request, data=data, storedprocfetch="CheckGSTReleaseExists", storedprocadd="AddGSTReleaseFromExcel" ) + + # Check if addition was successful + if gst.isSuccess: + print(f"GST Release Added: {data}") + else: + print(f"Failed to add GST Release: {gst.resultMessage}") self.isSuccess = gst.isSuccess self.resultMessage = str(gst.resultMessage) @@ -198,7 +104,6 @@ class GSTRelease: def GetAllGSTReleases(self): try: gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) - rows = gst.GetAllData(None, "GetAllGSTReleases") data = [] @@ -224,7 +129,6 @@ class GSTRelease: def GetGSTReleaseByID(self, gst_release_id): try: gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) - row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById") if row: diff --git a/static/js/invoice.js b/static/js/invoice.js index 9b3f2a0..d3e0778 100644 --- a/static/js/invoice.js +++ b/static/js/invoice.js @@ -1,62 +1,271 @@ -// Subcontractor autocomplete functionality - $(document).ready(function () { - $("#subcontractor").keyup(function () { +// $(document).ready(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(); if (query !== "") { - $.ajax({ - url: "/search_subcontractor", - method: "POST", - data: { query: query }, - success: function (data) { - $("#subcontractor_list").fadeIn().html(data); - } - }); + $.ajax({ + url: "/search_subcontractor", + method: "POST", + data: { query: query }, + success: function (data) { + $("#subcontractor_list").fadeIn().html(data); + } + }); } else { - $("#subcontractor_list").fadeOut(); + $("#subcontractor_list").fadeOut(); } - }); + }); - $(document).on("click", "li", function () { + $(document).on("click", "li", function () { $("#subcontractor").val($(this).text()); $("#subcontractor_id").val($(this).attr("data-id")); $("#subcontractor_list").fadeOut(); - }); }); - // Success Alert: show alert and reload after 3 seconds - function showSuccessAlert() { - const alertBox = document.getElementById("invoiceSuccessAlert"); - alertBox.classList.add("show"); - setTimeout(() => { - alertBox.classList.remove("show"); - // Reload page or redirect after alert hides - window.location.href = '/add_invoice'; - }, 3000); + // Focus + if (document.getElementById('subcontractor')) { + document.getElementById('subcontractor').focus(); } - // Submit form via AJAX - $("#invoiceForm").on("submit", function (e) { - e.preventDefault(); - let formData = $(this).serialize(); - $.ajax({ - url: '/add_invoice', - method: 'POST', - data: formData, - success: function (response) { - if(response.status === "success") { - showSuccessAlert(); - } else { - alert(response.message); - } - }, - error: function (xhr, status, error) { - alert("Submission failed: " + error); - } - }); - }); + // =============================== + // 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) { + 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 () { - document.getElementById('subcontractor').focus(); - }; \ No newline at end of file + $.ajax({ + 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 +}); \ No newline at end of file diff --git a/templates/add_gst_release.html b/templates/add_gst_release.html index f15e4fa..8d78e53 100644 --- a/templates/add_gst_release.html +++ b/templates/add_gst_release.html @@ -68,50 +68,49 @@ {% endwith %} + diff --git a/templates/add_invoice.html b/templates/add_invoice.html index 399fa07..e6372e9 100644 --- a/templates/add_invoice.html +++ b/templates/add_invoice.html @@ -1,176 +1,322 @@ -{% extends 'base.html' %} -{% block content %} +{% extends 'base.html' %} {% block content %} - - - Add Invoice - - - - + + + Add Invoice + + + + -{% if success == 'true' %} - {% endif %} -{% endwith %} -
+ + {% with messages = get_flashed_messages(with_categories=true) %} {% if + messages %} +
+ {% for category, message in messages %} +
{{ message }}
+ {% endfor %} +
+ {% endif %} {% endwith %} + +
-
+
-