mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-09-30 10:03:13 +00:00
Playwright-based menu scraper for Redefine Meals, self-contained HTML order form with S3/CloudFront hosting, DynamoDB-backed order submission via API Gateway, and automated payroll deduction reports via SES.
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
import json
|
|
import os
|
|
from datetime import datetime
|
|
from zoneinfo import ZoneInfo
|
|
|
|
from shared.db import current_week, get_form_status, put_order
|
|
|
|
EASTERN = ZoneInfo("America/New_York")
|
|
API_KEY = os.environ.get("FORM_API_KEY", "")
|
|
|
|
|
|
def lambda_handler(event, context):
|
|
method = event.get("requestContext", {}).get("http", {}).get("method", "GET")
|
|
path = event.get("rawPath", "")
|
|
|
|
if "/form-status/" in path:
|
|
return handle_form_status(event)
|
|
|
|
if method == "POST":
|
|
return handle_submit(event)
|
|
|
|
return response(405, {"error": "Method not allowed"})
|
|
|
|
|
|
def handle_form_status(event):
|
|
week = event.get("pathParameters", {}).get("week", current_week())
|
|
status = get_form_status(week)
|
|
return response(200, {"week": week, "status": status})
|
|
|
|
|
|
def handle_submit(event):
|
|
api_key = event.get("headers", {}).get("x-api-key", "")
|
|
if API_KEY and api_key != API_KEY:
|
|
return response(403, {"error": "Invalid API key"})
|
|
|
|
try:
|
|
body = json.loads(event.get("body", "{}"))
|
|
except json.JSONDecodeError:
|
|
return response(400, {"error": "Invalid JSON"})
|
|
|
|
name = body.get("employee_name", "").strip()
|
|
email = body.get("employee_email", "").strip()
|
|
items = body.get("items", [])
|
|
|
|
if not name:
|
|
return response(400, {"error": "Employee name is required"})
|
|
if not email:
|
|
return response(400, {"error": "Employee email is required"})
|
|
if not items or not any(i.get("quantity", 0) > 0 for i in items):
|
|
return response(400, {"error": "Please select at least one meal"})
|
|
|
|
week = current_week()
|
|
status = get_form_status(week)
|
|
if status == "closed":
|
|
return response(410, {"error": "Orders are closed for this week"})
|
|
if status == "not_found":
|
|
return response(404, {"error": "No menu available for this week"})
|
|
|
|
filtered_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 filtered_items)
|
|
|
|
slug = "".join(c if c.isalnum() or c in "- " else "" for c in name).strip().replace(" ", "-").lower()
|
|
|
|
order_data = {
|
|
"employee_name": name,
|
|
"employee_email": email,
|
|
"submitted_at": datetime.now(EASTERN).isoformat(),
|
|
"items": filtered_items,
|
|
"total": round(total, 2),
|
|
}
|
|
|
|
put_order(week, slug, order_data)
|
|
|
|
return response(200, {"status": "ok", "message": f"Order saved for {name}", "total": order_data["total"]})
|
|
|
|
|
|
def response(status_code: int, body: dict) -> dict:
|
|
return {
|
|
"statusCode": status_code,
|
|
"headers": {"Content-Type": "application/json"},
|
|
"body": json.dumps(body),
|
|
}
|