From 04ebc6f2d20657f6fd4a41db94ac7265afa42c54 Mon Sep 17 00:00:00 2001 From: def Date: Sun, 8 Mar 2026 15:46:38 +0000 Subject: [PATCH] Add v0.0.7 invoice system --- VERSION | 2 +- backend/app.py | 162 +++++++++++++++++------------------ templates/invoices/list.html | 45 ++++++++++ templates/invoices/new.html | 63 ++++++++++++++ 4 files changed, 190 insertions(+), 82 deletions(-) create mode 100644 templates/invoices/list.html create mode 100644 templates/invoices/new.html diff --git a/VERSION b/VERSION index 1750564..5a5831a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.6 +0.0.7 diff --git a/backend/app.py b/backend/app.py index e380305..7e9bc94 100644 --- a/backend/app.py +++ b/backend/app.py @@ -12,9 +12,10 @@ app = Flask( def index(): return """

OTB Billing

-

Version 0.0.6

+

Version 0.0.7

Clients

Services

+

Invoices

DB Test

""" @@ -39,118 +40,117 @@ def clients(): conn.close() return render_template("clients/list.html", clients=clients) -@app.route("/clients/new", methods=["GET", "POST"]) -def new_client(): - if request.method == "POST": - company_name = request.form["company_name"] - contact_name = request.form["contact_name"] - email = request.form["email"] - phone = request.form["phone"] - - conn = get_db_connection() - cursor = conn.cursor(dictionary=True) - cursor.execute("SELECT MAX(id) AS last_id FROM clients") - result = cursor.fetchone() - last_number = result["last_id"] if result["last_id"] else 0 +@app.route("/services") +def services(): + conn = get_db_connection() + cursor = conn.cursor(dictionary=True) - client_code = generate_client_code(company_name, last_number) + cursor.execute(""" + SELECT s.*, c.client_code, c.company_name + FROM services s + JOIN clients c ON s.client_id = c.id + ORDER BY s.id DESC + """) - cursor = conn.cursor() - cursor.execute( - """ - INSERT INTO clients - (client_code, company_name, contact_name, email, phone) - VALUES (%s, %s, %s, %s, %s) - """, - (client_code, company_name, contact_name, email, phone) - ) - conn.commit() - conn.close() + services = cursor.fetchall() + conn.close() - return redirect("/clients") + return render_template("services/list.html", services=services) - return render_template("clients/new.html") +@app.route("/invoices") +def invoices(): -@app.route("/services") -def services(): conn = get_db_connection() cursor = conn.cursor(dictionary=True) - cursor.execute( - """ + + cursor.execute(""" SELECT - s.*, + i.*, c.client_code, c.company_name - FROM services s - JOIN clients c ON s.client_id = c.id - ORDER BY s.id DESC - """ - ) - services = cursor.fetchall() + FROM invoices i + JOIN clients c ON i.client_id = c.id + ORDER BY i.id DESC + """) + + invoices = cursor.fetchall() conn.close() - return render_template("services/list.html", services=services) -@app.route("/services/new", methods=["GET", "POST"]) -def new_service(): + return render_template("invoices/list.html", invoices=invoices) + +@app.route("/invoices/new", methods=["GET","POST"]) +def new_invoice(): + conn = get_db_connection() cursor = conn.cursor(dictionary=True) if request.method == "POST": + client_id = request.form["client_id"] - service_name = request.form["service_name"] - service_type = request.form["service_type"] - billing_cycle = request.form["billing_cycle"] + service_id = request.form["service_id"] currency_code = request.form["currency_code"] - recurring_amount = request.form["recurring_amount"] - status = request.form["status"] - start_date = request.form["start_date"] or None - description = request.form["description"] + total_amount = request.form["total_amount"] + due_at = request.form["due_at"] + notes = request.form["notes"] - cursor.execute("SELECT MAX(id) AS last_id FROM services") + cursor.execute("SELECT MAX(id) as last_id FROM invoices") result = cursor.fetchone() - last_number = result["last_id"] if result["last_id"] else 0 - service_code = generate_service_code(service_name, last_number) - insert_cursor = conn.cursor() - insert_cursor.execute( - """ - INSERT INTO services + number = (result["last_id"] or 0) + 1 + invoice_number = f"INV-{number:04d}" + + insert = conn.cursor() + + insert.execute(""" + INSERT INTO invoices ( client_id, - service_code, - service_name, - service_type, - billing_cycle, - status, + service_id, + invoice_number, currency_code, - recurring_amount, - start_date, - description - ) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) - """, - ( - client_id, - service_code, - service_name, - service_type, - billing_cycle, + total_amount, + subtotal_amount, + issued_at, + due_at, status, - currency_code, - recurring_amount, - start_date, - description + notes ) - ) + VALUES (%s,%s,%s,%s,%s,%s,NOW(),%s,'pending',%s) + """, + ( + client_id, + service_id, + invoice_number, + currency_code, + total_amount, + total_amount, + due_at, + notes + )) + conn.commit() conn.close() - return redirect("/services") + return redirect("/invoices") - cursor.execute("SELECT id, client_code, company_name FROM clients ORDER BY company_name ASC") + cursor.execute(""" + SELECT id, client_code, company_name + FROM clients + ORDER BY company_name + """) clients = cursor.fetchall() + + cursor.execute(""" + SELECT id, service_code, service_name + FROM services + ORDER BY service_name + """) + services = cursor.fetchall() + conn.close() - return render_template("services/new.html", clients=clients) + + return render_template("invoices/new.html", clients=clients, services=services) + if __name__ == "__main__": app.run(host="0.0.0.0", port=5050) diff --git a/templates/invoices/list.html b/templates/invoices/list.html new file mode 100644 index 0000000..cf04fba --- /dev/null +++ b/templates/invoices/list.html @@ -0,0 +1,45 @@ + + + +Invoices + + + + +

Invoices

+ +

Home

+

Create Invoice

+ + + + + + + + + + + + + + +{% for i in invoices %} + + + + + + + + + + + + +{% endfor %} + +
IDInvoiceClientCurrencyTotalStatusIssuedDue
{{ i.id }}{{ i.invoice_number }}{{ i.client_code }} - {{ i.company_name }}{{ i.currency_code }}{{ i.total_amount }}{{ i.status }}{{ i.issued_at }}{{ i.due_at }}
+ + + diff --git a/templates/invoices/new.html b/templates/invoices/new.html new file mode 100644 index 0000000..0ae4d09 --- /dev/null +++ b/templates/invoices/new.html @@ -0,0 +1,63 @@ + + + +New Invoice + + + + +

Create Invoice

+ +
+ +

+Client
+ +

+ +

+Service
+ +

+ +

+Currency
+ +

+ +

+Total Amount
+ +

+ +

+Due Date
+ +

+ +

+Notes
+ +

+ +

+ +

+ +
+ + +