mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-09-30 08:53:13 +00:00
Apply ruff check --fix and ruff format across all Python files to pass CI pipeline. Remove unused imports (os, sys), fix f-strings without placeholders. Update README to reflect sync-roster Lambda, corrected shared layer path, and current project structure.
129 lines
3.5 KiB
Python
129 lines
3.5 KiB
Python
"""
|
|
Lightweight Flask server for the meal order form.
|
|
|
|
Serves the generated HTML form and handles order submissions.
|
|
Orders are saved as JSON files in the orders directory, one per employee per week.
|
|
"""
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from flask import Flask, jsonify, request, send_file
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
CONFIG_PATH = PROJECT_ROOT / "config.json"
|
|
OUTPUT_DIR = PROJECT_ROOT / "output"
|
|
ORDERS_DIR = PROJECT_ROOT / "orders"
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
def load_config():
|
|
with open(CONFIG_PATH) as f:
|
|
return json.load(f)
|
|
|
|
|
|
def current_week() -> str:
|
|
return datetime.now().strftime("%Y-W%U")
|
|
|
|
|
|
def latest_menu_file() -> Path | None:
|
|
files = sorted(OUTPUT_DIR.glob("menu-*.json"), reverse=True)
|
|
return files[0] if files else None
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
form_file = OUTPUT_DIR / f"order-form-{current_week()}.html"
|
|
if not form_file.exists():
|
|
return "No order form generated for this week. Run generate_form.py first.", 404
|
|
return send_file(form_file)
|
|
|
|
|
|
@app.route("/api/menu")
|
|
def get_menu():
|
|
menu_file = latest_menu_file()
|
|
if not menu_file:
|
|
return jsonify(
|
|
{"error": "No menu data available. Run scrape_menu.py first."}
|
|
), 404
|
|
with open(menu_file) as f:
|
|
return jsonify(json.load(f))
|
|
|
|
|
|
@app.route("/api/roster")
|
|
def get_roster():
|
|
config = load_config()
|
|
return jsonify(config.get("roster", []))
|
|
|
|
|
|
@app.route("/api/submit-order", methods=["POST"])
|
|
def submit_order():
|
|
data = request.get_json()
|
|
if not data:
|
|
return jsonify({"error": "No data received"}), 400
|
|
|
|
name = data.get("employee_name", "").strip()
|
|
email = data.get("employee_email", "").strip()
|
|
items = data.get("items", [])
|
|
|
|
if not name:
|
|
return jsonify({"error": "Employee name is required"}), 400
|
|
if not email:
|
|
return jsonify({"error": "Employee email is required"}), 400
|
|
if not items or not any(i.get("quantity", 0) > 0 for i in items):
|
|
return jsonify({"error": "Please select at least one meal"}), 400
|
|
|
|
week = current_week()
|
|
week_dir = ORDERS_DIR / week
|
|
week_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
safe_name = (
|
|
"".join(c if c.isalnum() or c in "-_ " else "" for c in name)
|
|
.strip()
|
|
.replace(" ", "-")
|
|
.lower()
|
|
)
|
|
order_file = week_dir / f"{safe_name}.json"
|
|
|
|
order = {
|
|
"employee_name": name,
|
|
"employee_email": email,
|
|
"week": week,
|
|
"submitted_at": datetime.now().isoformat(),
|
|
"items": [i for i in items if i.get("quantity", 0) > 0],
|
|
"total": sum(
|
|
(i.get("price", 0) or 0) * i.get("quantity", 0)
|
|
for i in items
|
|
if i.get("quantity", 0) > 0
|
|
),
|
|
}
|
|
|
|
with open(order_file, "w") as f:
|
|
json.dump(order, f, indent=2)
|
|
|
|
return jsonify(
|
|
{"status": "ok", "message": f"Order saved for {name}", "total": order["total"]}
|
|
)
|
|
|
|
|
|
@app.route("/api/orders/<week>")
|
|
def get_orders(week: str):
|
|
week_dir = ORDERS_DIR / week
|
|
if not week_dir.exists():
|
|
return jsonify({"orders": [], "week": week})
|
|
|
|
orders = []
|
|
for f in sorted(week_dir.glob("*.json")):
|
|
with open(f) as fh:
|
|
orders.append(json.load(fh))
|
|
|
|
return jsonify({"orders": orders, "week": week})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
ORDERS_DIR.mkdir(exist_ok=True)
|
|
print(f"Menu file: {latest_menu_file()}")
|
|
print(f"Orders dir: {ORDERS_DIR}")
|
|
app.run(host="0.0.0.0", port=5050, debug=True)
|