249 lines
9.0 KiB
Python
249 lines
9.0 KiB
Python
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)
|