Browse Source

Add v0.1.5 service edit page

main
def 2 weeks ago
parent
commit
21340c27cb
  1. 2
      VERSION
  2. 102
      backend/app.py
  3. 115
      templates/services/edit.html
  4. 2
      templates/services/list.html

2
VERSION

@ -1 +1 @@
0.1.4 0.1.5

102
backend/app.py

@ -303,6 +303,108 @@ def new_service():
conn.close() conn.close()
return render_template("services/new.html", clients=clients) return render_template("services/new.html", clients=clients)
@app.route("/services/edit/<int:service_id>", methods=["GET", "POST"])
def edit_service(service_id):
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
if request.method == "POST":
client_id = request.form.get("client_id", "").strip()
service_name = request.form.get("service_name", "").strip()
service_type = request.form.get("service_type", "").strip()
billing_cycle = request.form.get("billing_cycle", "").strip()
currency_code = request.form.get("currency_code", "").strip()
recurring_amount = request.form.get("recurring_amount", "").strip()
status = request.form.get("status", "").strip()
start_date = request.form.get("start_date", "").strip()
description = request.form.get("description", "").strip()
errors = []
if not client_id:
errors.append("Client is required.")
if not service_name:
errors.append("Service name is required.")
if not service_type:
errors.append("Service type is required.")
if not billing_cycle:
errors.append("Billing cycle is required.")
if not currency_code:
errors.append("Currency code is required.")
if not recurring_amount:
errors.append("Recurring amount is required.")
if not status:
errors.append("Status is required.")
if not errors:
try:
recurring_amount_value = float(recurring_amount)
if recurring_amount_value < 0:
errors.append("Recurring amount cannot be negative.")
except ValueError:
errors.append("Recurring amount must be a valid number.")
if errors:
cursor.execute("""
SELECT s.*, c.company_name
FROM services s
LEFT JOIN clients c ON s.client_id = c.id
WHERE s.id = %s
""", (service_id,))
service = cursor.fetchone()
cursor.execute("SELECT id, client_code, company_name FROM clients ORDER BY company_name ASC")
clients = cursor.fetchall()
conn.close()
return render_template("services/edit.html", service=service, clients=clients, errors=errors)
update_cursor = conn.cursor()
update_cursor.execute("""
UPDATE services
SET client_id = %s,
service_name = %s,
service_type = %s,
billing_cycle = %s,
status = %s,
currency_code = %s,
recurring_amount = %s,
start_date = %s,
description = %s
WHERE id = %s
""", (
client_id,
service_name,
service_type,
billing_cycle,
status,
currency_code,
recurring_amount,
start_date or None,
description or None,
service_id
))
conn.commit()
conn.close()
return redirect("/services")
cursor.execute("""
SELECT s.*, c.company_name
FROM services s
LEFT JOIN clients c ON s.client_id = c.id
WHERE s.id = %s
""", (service_id,))
service = cursor.fetchone()
cursor.execute("SELECT id, client_code, company_name FROM clients ORDER BY company_name ASC")
clients = cursor.fetchall()
conn.close()
if not service:
return "Service not found", 404
return render_template("services/edit.html", service=service, clients=clients, errors=[])
@app.route("/invoices") @app.route("/invoices")
def invoices(): def invoices():
refresh_overdue_invoices() refresh_overdue_invoices()

115
templates/services/edit.html

@ -0,0 +1,115 @@
<!doctype html>
<html>
<head>
<title>Edit Service</title>
</head>
<body>
<h1>Edit Service</h1>
<p><a href="/">Home</a></p>
<p><a href="/services">Back to Services</a></p>
{% if errors %}
<div style="border:1px solid red; padding:10px; margin-bottom:15px;">
<strong>Please fix the following:</strong>
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form method="post">
<p>
Service Code<br>
<input value="{{ service.service_code }}" readonly>
</p>
<p>
Client *<br>
<select name="client_id" required>
<option value="">Select client</option>
{% for c in clients %}
<option value="{{ c.id }}" {% if service.client_id == c.id %}selected{% endif %}>
{{ c.client_code }} - {{ c.company_name }}
</option>
{% endfor %}
</select>
</p>
<p>
Service Name *<br>
<input name="service_name" value="{{ service.service_name }}" required>
</p>
<p>
Service Type *<br>
<select name="service_type" required>
<option value="hosting" {% if service.service_type == 'hosting' %}selected{% endif %}>hosting</option>
<option value="rpc" {% if service.service_type == 'rpc' %}selected{% endif %}>rpc</option>
<option value="explorer" {% if service.service_type == 'explorer' %}selected{% endif %}>explorer</option>
<option value="node" {% if service.service_type == 'node' %}selected{% endif %}>node</option>
<option value="ipfs" {% if service.service_type == 'ipfs' %}selected{% endif %}>ipfs</option>
<option value="consulting" {% if service.service_type == 'consulting' %}selected{% endif %}>consulting</option>
<option value="other" {% if service.service_type == 'other' %}selected{% endif %}>other</option>
</select>
</p>
<p>
Billing Cycle *<br>
<select name="billing_cycle" required>
<option value="one_time" {% if service.billing_cycle == 'one_time' %}selected{% endif %}>one_time</option>
<option value="monthly" {% if service.billing_cycle == 'monthly' %}selected{% endif %}>monthly</option>
<option value="quarterly" {% if service.billing_cycle == 'quarterly' %}selected{% endif %}>quarterly</option>
<option value="yearly" {% if service.billing_cycle == 'yearly' %}selected{% endif %}>yearly</option>
<option value="manual" {% if service.billing_cycle == 'manual' %}selected{% endif %}>manual</option>
</select>
</p>
<p>
Currency Code *<br>
<select name="currency_code" required>
<option value="CAD" {% if service.currency_code == 'CAD' %}selected{% endif %}>CAD</option>
<option value="ETHO" {% if service.currency_code == 'ETHO' %}selected{% endif %}>ETHO</option>
<option value="EGAZ" {% if service.currency_code == 'EGAZ' %}selected{% endif %}>EGAZ</option>
<option value="ALT" {% if service.currency_code == 'ALT' %}selected{% endif %}>ALT</option>
</select>
</p>
<p>
Recurring Amount *<br>
<input type="number" step="0.00000001" min="0" name="recurring_amount" value="{{ service.recurring_amount }}" required>
</p>
<p>
Status *<br>
<select name="status" required>
<option value="pending" {% if service.status == 'pending' %}selected{% endif %}>pending</option>
<option value="active" {% if service.status == 'active' %}selected{% endif %}>active</option>
<option value="suspended" {% if service.status == 'suspended' %}selected{% endif %}>suspended</option>
<option value="cancelled" {% if service.status == 'cancelled' %}selected{% endif %}>cancelled</option>
</select>
</p>
<p>
Start Date<br>
<input type="date" name="start_date" value="{{ service.start_date }}">
</p>
<p>
Description<br>
<textarea name="description" rows="5" cols="60">{{ service.description or '' }}</textarea>
</p>
<p>
<button type="submit">Save Service</button>
</p>
</form>
{% include "footer.html" %}
</body>
</html>

2
templates/services/list.html

@ -22,6 +22,7 @@
<th>Amount</th> <th>Amount</th>
<th>Status</th> <th>Status</th>
<th>Start Date</th> <th>Start Date</th>
<th>Actions</th>
</tr> </tr>
{% for s in services %} {% for s in services %}
@ -36,6 +37,7 @@
<td>{{ s.recurring_amount|money(s.currency_code) }}</td> <td>{{ s.recurring_amount|money(s.currency_code) }}</td>
<td>{{ s.status }}</td> <td>{{ s.status }}</td>
<td>{{ s.start_date }}</td> <td>{{ s.start_date }}</td>
<td><a href="/services/edit/{{ s.id }}">Edit</a></td>
</tr> </tr>
{% endfor %} {% endfor %}

Loading…
Cancel
Save