Files

249 lines
9.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from flask import Flask, request, jsonify
from database import *
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'photos')
app.config['URL_PREFIX'] = '/uploads' # public URL prefix
# make sure the folder exists
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# helper to build a public URL
def public_url(filename: str) -> str:
return f"{app.config['URL_PREFIX']}/{filename}"
# Initialise database on startup
initialize_db()
# ----------------------------- Users -----------------------------
@app.route("/users", methods=["GET", "POST"])
def users():
if request.method == "GET":
# Optional query parameters
name = request.args.get("name")
id = request.args.get("id", type=int)
username = request.args.get("username")
fields = request.args.get("fields")
fields = fields.split(",") if fields else None
users = get_user(name=name, id=id, username=username, fields=fields)
return jsonify(users)
if request.method == "POST":
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
name = data.get("name")
age = data.get("age")
photo = data.get("photo")
username = data.get("username")
if not all([name, age, username]):
return jsonify({"error": "name, age and username required"}), 400
result = add_user(name, age, photo, username)
return jsonify(result), 201
@app.route("/users/<int:user_id>", methods=["PUT"])
def update_user_route(user_id: int):
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
name = data.get("name")
photo = data.get("photo")
settings = data.get("settings")
result = update_user(user_id, name=name, photo=photo, settings=settings)
return jsonify(result)
# ----------------------------- Providers -----------------------------
@app.route("/providers", methods=["GET", "POST"])
def providers():
if request.method == "GET":
name = request.args.get("name")
id = request.args.get("id", type=int)
phone = request.args.get("phone")
fields = request.args.get("fields")
fields = fields.split(",") if fields else None
provs = get_provider(name=name, id=id, phone=phone, fields=fields)
return jsonify(provs)
if request.method == "POST":
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
name = data.get("name")
age = data.get("age")
photo = data.get("photo")
phone = data.get("phone")
rates = data.get("rates", {})
private = data.get("private", False)
if not all([name, age, phone]):
return jsonify({"error": "name, age and phone required"}), 400
result = add_provider(name, age, photo, phone, rates, private)
return jsonify(result), 201
@app.route("/providers/<int:prov_id>", methods=["PUT"])
def update_provider_route(prov_id: int):
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
name = data.get("name")
phone = data.get("phone")
rates = data.get("rates")
private = data.get("private")
photo = data.get("photo")
result = update_provider(prov_id, name=name, phone=phone, rates=rates, private=private, photo=photo)
return jsonify(result)
# ----------------------------- Visits -----------------------------
@app.route("/visits", methods=["GET", "POST"])
def visits():
if request.method == "GET":
provider = request.args.get("provider", type=int)
user = request.args.get("user", type=int)
start = request.args.get("start")
end = request.args.get("end")
date_range = [start, end] if start and end else None
visits_list = get_visits(provider=provider, user=user, date_range=date_range)
return jsonify(visits_list)
if request.method == "POST":
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
user_ids = data.get("user_ids", [])
provider_ids = data.get("provider_ids", [])
cost = data.get("cost")
location = data.get("location")
time = data.get("time")
if not (user_ids and provider_ids and time):
return jsonify({"error": "user_ids, provider_ids and time required"}), 400
result = add_visit(user_ids, provider_ids, cost, location, time)
return jsonify(result), 201
@app.route("/visits/<int:visit_id>", methods=["PUT"])
def update_visit_route(visit_id: int):
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
user_ids = data.get("user_ids")
provider_ids = data.get("provider_ids")
cost = data.get("cost")
location = data.get("location")
time = data.get("time")
result = update_visit(visit_id, user_ids=user_ids, provider_ids=provider_ids,
cost=cost, location=location, time=time)
return jsonify(result)
# ----------------------------- Settings -----------------------------
@app.route("/settings", methods=["GET", "POST"])
def settings_collection():
"""Handle collection of settings.
* GET: Return all settings.
* POST: Add or replace a setting. Expects JSON with ``name`` and ``value``.
"""
if request.method == "GET":
# Return all settings
print(view_settings())
return jsonify(view_settings())
if request.method == "POST":
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
name = data.get("name")
value = data.get("value")
if not name or value is None:
return jsonify({"error": "name and value required"}), 400
result = add_setting(name, value)
print(result)
return jsonify(result), 201
@app.route("/settings/<string:name>", methods=["GET", "PUT"])
def setting_detail(name: str):
"""Retrieve or update a single setting.
* GET: Return the setting with the given name.
* PUT: Update the setting value. Expects JSON with ``value``.
"""
if request.method == "GET":
rows = view_settings([name])
if not rows:
return jsonify({"error": "Setting not found"}), 404
print(rows[0])
return jsonify(rows[0])
if request.method == "PUT":
data = request.get_json()
if not data:
return jsonify({"error": "Missing JSON body"}), 400
value = data.get("value")
if value is None:
return jsonify({"error": "value required"}), 400
result = change_setting(name, value)
print(result)
return jsonify(result)
# ----------------------------- Photos -----------------------------
# photo upload endpoint
@app.route('/api/providers/<int:provider_id>/photos', methods=['POST'])
def upload_photos(provider_id):
if 'photos' not in request.files:
return jsonify({'error': 'No files uploaded'}), 400
files = request.files.getlist('photos')
if not files:
return jsonify({'error': 'No files in list'}), 400
allowed_ext = {'.jpg', '.jpeg', '.png', '.gif'}
saved_filenames = []
for f in files:
if f.filename == '':
continue
filename = secure_filename(f.filename)
ext = os.path.splitext(filename)[1].lower()
if ext not in allowed_ext:
return jsonify({'error': f'Unsupported file type: {ext}'}), 400
# rename to avoid collisions
new_name = f"{uuid.uuid4().hex}{ext}"
f.save(os.path.join(app.config['UPLOAD_FOLDER'], new_name))
saved_filenames.append(public_url(new_name))
# Merge with any pre‑existing photos
existing = db.fetch(f"SELECT photos FROM providers WHERE id=?", (provider_id,))[0][0]
try:
photos = json.loads(existing)
except Exception:
photos = []
photos.extend(saved_filenames)
db.execute("UPDATE providers SET photos = %s WHERE id = %s",
(json.dumps(photos), provider_id))
return jsonify({'success': True, 'photos': photos}), 200
# Endpoint to change the main photo
@app.route('/api/providers/<int:provider_id>/main_photo', methods=['PUT'])
def set_main_photo(provider_id):
data = request.get_json()
url = data.get('url')
if not url:
return jsonify({'error': 'Missing url'}), 400
# Validate that the URL belongs to this provider
photos = db.fetch(f"SELECT photos FROM providers WHERE id=?", (provider_id,))[0][0]
if json.loads(photos).count(url) == 0:
return jsonify({'error': 'URL not part of this provider'}), 400
db.execute("UPDATE providers SET main_photo = %s WHERE id = %s",
(url, provider_id))
return jsonify({'success': True, 'main_photo': url})
# Run the app if this file is executed directly
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)