import json import os from decimal import Decimal from shared.db import current_week, get_orders, get_roster, get_summary from shared.slack import post_channel_message, send_dm class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): return float(o) return super().default(o) def lambda_handler(event, context): event_type = event.get("event", "") if event_type == "menu_published": return handle_menu_published(event) elif event_type == "orders_aggregated": return handle_orders_aggregated(event) elif event_type == "reminder": return handle_reminder(event) return {"error": f"Unknown event type: {event_type}"} def handle_menu_published(event): form_url = os.environ.get("FORM_URL", "") week = event.get("week", current_week()) meal_count = event.get("meal_count", "") text = "This week's meal order is open! Deadline: Thursday 6pm." blocks = [ { "type": "header", "text": {"type": "plain_text", "text": "Meal Order Open"}, }, { "type": "section", "text": { "type": "mrkdwn", "text": ( f"*<{form_url}|Place your order>*\n\n" f"*Deadline:* Thursday 6pm\n" f"*Menu:* {meal_count} meals available" ), }, }, ] post_channel_message(text, blocks) return {"status": "notified", "event": "menu_published", "week": week} def handle_orders_aggregated(event): week = event.get("week", current_week()) summary = get_summary(week) if not summary: return {"status": "no_summary", "week": week} total_employees = int(summary.get("total_employees", 0)) total_meals = int(summary.get("total_meals", 0)) grand_total = float(summary.get("grand_total", 0)) meal_lines = [] for m in summary.get("meals", []): meal_lines.append(f"{m['meal']}: *{int(m['quantity'])}*") meal_list = "\n".join(meal_lines) text = f"Meal orders closed for {week}. {total_employees} employees, {total_meals} meals, ${grand_total:.2f} total." blocks = [ { "type": "header", "text": {"type": "plain_text", "text": f"Meal Orders Closed — {week}"}, }, { "type": "section", "text": { "type": "mrkdwn", "text": ( f"*{total_employees}* employees ordered\n" f"*{total_meals}* total meals\n" f"*${grand_total:.2f}* grand total" ), }, }, {"type": "divider"}, { "type": "section", "text": { "type": "mrkdwn", "text": f"*Order for Redefine Meals:*\n{meal_list}", }, }, ] post_channel_message(text, blocks) return {"status": "notified", "event": "orders_aggregated", "week": week} def handle_reminder(event): week = event.get("week", current_week()) form_url = os.environ.get("FORM_URL", "") roster = get_roster() if not roster: return {"status": "no_roster"} orders = get_orders(week) ordered_emails = {o["employee_email"].lower() for o in orders} missing = [emp for emp in roster if emp["email"].lower() not in ordered_emails] dm_count = 0 for emp in missing: slack_id = emp.get("slack_user_id") if not slack_id: continue send_dm( slack_id, f"Meal orders close at 6pm today. Place your order: {form_url}", blocks=[ { "type": "section", "text": { "type": "mrkdwn", "text": ( f"Hey {emp['name'].split()[0]}! Meal orders close at *6pm today*.\n\n" f"*<{form_url}|Place your order>*" ), }, } ], ) dm_count += 1 return { "status": "reminders_sent", "week": week, "dm_count": dm_count, "missing_count": len(missing), }