Browse Source

Add v0.0.7 invoice system

main
def 2 weeks ago
parent
commit
04ebc6f2d2
  1. 2
      VERSION
  2. 162
      backend/app.py
  3. 45
      templates/invoices/list.html
  4. 63
      templates/invoices/new.html

2
VERSION

@ -1 +1 @@
0.0.6 0.0.7

162
backend/app.py

@ -12,9 +12,10 @@ app = Flask(
def index(): def index():
return """ return """
<h1>OTB Billing</h1> <h1>OTB Billing</h1>
<p>Version 0.0.6</p> <p>Version 0.0.7</p>
<p><a href="/clients">Clients</a></p> <p><a href="/clients">Clients</a></p>
<p><a href="/services">Services</a></p> <p><a href="/services">Services</a></p>
<p><a href="/invoices">Invoices</a></p>
<p><a href="/dbtest">DB Test</a></p> <p><a href="/dbtest">DB Test</a></p>
""" """
@ -39,118 +40,117 @@ def clients():
conn.close() conn.close()
return render_template("clients/list.html", clients=clients) return render_template("clients/list.html", clients=clients)
@app.route("/clients/new", methods=["GET", "POST"]) @app.route("/services")
def new_client(): def services():
if request.method == "POST": conn = get_db_connection()
company_name = request.form["company_name"] cursor = conn.cursor(dictionary=True)
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
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() services = cursor.fetchall()
cursor.execute( conn.close()
"""
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()
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() conn = get_db_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
cursor.execute(
""" cursor.execute("""
SELECT SELECT
s.*, i.*,
c.client_code, c.client_code,
c.company_name c.company_name
FROM services s FROM invoices i
JOIN clients c ON s.client_id = c.id JOIN clients c ON i.client_id = c.id
ORDER BY s.id DESC ORDER BY i.id DESC
""" """)
)
services = cursor.fetchall() invoices = cursor.fetchall()
conn.close() conn.close()
return render_template("services/list.html", services=services)
@app.route("/services/new", methods=["GET", "POST"]) return render_template("invoices/list.html", invoices=invoices)
def new_service():
@app.route("/invoices/new", methods=["GET","POST"])
def new_invoice():
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
if request.method == "POST": if request.method == "POST":
client_id = request.form["client_id"] client_id = request.form["client_id"]
service_name = request.form["service_name"] service_id = request.form["service_id"]
service_type = request.form["service_type"]
billing_cycle = request.form["billing_cycle"]
currency_code = request.form["currency_code"] currency_code = request.form["currency_code"]
recurring_amount = request.form["recurring_amount"] total_amount = request.form["total_amount"]
status = request.form["status"] due_at = request.form["due_at"]
start_date = request.form["start_date"] or None notes = request.form["notes"]
description = request.form["description"]
cursor.execute("SELECT MAX(id) AS last_id FROM services") cursor.execute("SELECT MAX(id) as last_id FROM invoices")
result = cursor.fetchone() 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() number = (result["last_id"] or 0) + 1
insert_cursor.execute( invoice_number = f"INV-{number:04d}"
"""
INSERT INTO services insert = conn.cursor()
insert.execute("""
INSERT INTO invoices
( (
client_id, client_id,
service_code, service_id,
service_name, invoice_number,
service_type,
billing_cycle,
status,
currency_code, currency_code,
recurring_amount, total_amount,
start_date, subtotal_amount,
description issued_at,
) due_at,
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
(
client_id,
service_code,
service_name,
service_type,
billing_cycle,
status, status,
currency_code, notes
recurring_amount,
start_date,
description
) )
) 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.commit()
conn.close() 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() clients = cursor.fetchall()
cursor.execute("""
SELECT id, service_code, service_name
FROM services
ORDER BY service_name
""")
services = cursor.fetchall()
conn.close() conn.close()
return render_template("services/new.html", clients=clients)
return render_template("invoices/new.html", clients=clients, services=services)
if __name__ == "__main__": if __name__ == "__main__":
app.run(host="0.0.0.0", port=5050) app.run(host="0.0.0.0", port=5050)

45
templates/invoices/list.html

@ -0,0 +1,45 @@
<!doctype html>
<html>
<head>
<title>Invoices</title>
</head>
<body>
<h1>Invoices</h1>
<p><a href="/">Home</a></p>
<p><a href="/invoices/new">Create Invoice</a></p>
<table border="1" cellpadding="6">
<tr>
<th>ID</th>
<th>Invoice</th>
<th>Client</th>
<th>Currency</th>
<th>Total</th>
<th>Status</th>
<th>Issued</th>
<th>Due</th>
</tr>
{% for i in invoices %}
<tr>
<td>{{ i.id }}</td>
<td>{{ i.invoice_number }}</td>
<td>{{ i.client_code }} - {{ i.company_name }}</td>
<td>{{ i.currency_code }}</td>
<td>{{ i.total_amount }}</td>
<td>{{ i.status }}</td>
<td>{{ i.issued_at }}</td>
<td>{{ i.due_at }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>

63
templates/invoices/new.html

@ -0,0 +1,63 @@
<!doctype html>
<html>
<head>
<title>New Invoice</title>
</head>
<body>
<h1>Create Invoice</h1>
<form method="post">
<p>
Client<br>
<select name="client_id">
{% for c in clients %}
<option value="{{ c.id }}">{{ c.client_code }} - {{ c.company_name }}</option>
{% endfor %}
</select>
</p>
<p>
Service<br>
<select name="service_id">
{% for s in services %}
<option value="{{ s.id }}">{{ s.service_code }} - {{ s.service_name }}</option>
{% endfor %}
</select>
</p>
<p>
Currency<br>
<select name="currency_code">
<option value="CAD">CAD</option>
<option value="ETHO">ETHO</option>
<option value="EGAZ">EGAZ</option>
<option value="ALT">ALT</option>
</select>
</p>
<p>
Total Amount<br>
<input type="number" step="0.00000001" name="total_amount">
</p>
<p>
Due Date<br>
<input type="date" name="due_at">
</p>
<p>
Notes<br>
<textarea name="notes"></textarea>
</p>
<p>
<button type="submit">Create Invoice</button>
</p>
</form>
</body>
</html>
Loading…
Cancel
Save