meal-order-manager/functions/submit_order/handler.py
Adam Moussa a8adbdc116
Some checks are pending
Deploy / deploy (push) Waiting to run
Switch to orders.seahaven.com, add roster dropdown, fix deadline (#9)
- Change custom domain from orders.seahavenind.com to
  orders.seahaven.com to match other subdomain conventions
- Add GET /api/roster endpoint returning employee names/emails
- Replace name/email text inputs with dropdown populated from
  roster API (falls back to embedded roster for local dev)
- Fix order deadline text from Wednesday to Thursday 11:59 PM
- Fix Slack API calls: use form-urlencoded for conversations and
  users methods that reject JSON body encoding
2026-05-12 20:16:46 -04:00

111 lines
3.1 KiB
Python

import json
import os
from datetime import datetime
from zoneinfo import ZoneInfo
from shared.db import current_week, get_form_status, get_roster, put_order
from shared.secrets import get_secret
EASTERN = ZoneInfo("America/New_York")
_api_key = None
def _get_api_key() -> str:
global _api_key
if _api_key is None:
_api_key = get_secret(os.environ["FORM_API_KEY_SECRET"])
return _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 "/roster" in path:
return handle_roster()
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_roster():
roster = get_roster()
employees = [{"name": e["name"], "email": e["email"]} for e in roster]
return response(200, {"employees": employees})
def handle_submit(event):
api_key = event.get("headers", {}).get("x-api-key", "")
if api_key != _get_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),
}