Browse Source

Add v0.0.7 invoice system

main
def 2 weeks ago
parent
commit
04ebc6f2d2
  1. 2
      VERSION
  2. 150
      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

150
backend/app.py

@ -12,9 +12,10 @@ app = Flask(
def index():
return """
<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="/services">Services</a></p>
<p><a href="/invoices">Invoices</a></p>
<p><a href="/dbtest">DB Test</a></p>
"""
@ -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"]
@app.route("/services")
def services():
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()
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()
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
total_amount,
subtotal_amount,
issued_at,
due_at,
status,
notes
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
VALUES (%s,%s,%s,%s,%s,%s,NOW(),%s,'pending',%s)
""",
(
client_id,
service_code,
service_name,
service_type,
billing_cycle,
status,
service_id,
invoice_number,
currency_code,
recurring_amount,
start_date,
description
)
)
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)

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