From e6bef44a74a71103f7af24f62fc3eb7b70df6993 Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Wed, 13 May 2026 11:35:48 -0400 Subject: [PATCH] Add discount settings and two-tier pricing to order aggregation Settings CRUD (get_settings/put_settings) for DynamoDB CONFIG#SETTINGS item. Aggregation now tracks bulk_price and employee_price separately, with grand_total (company cost) and employee_total (payroll deductions). --- config.json | 5 ++++- functions/aggregate_orders/handler.py | 18 ++++++++++++++---- src/aggregator/aggregate.py | 23 +++++++++++++++++++---- src/shared/shared/db.py | 16 ++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/config.json b/config.json index 6904a34..002e184 100644 --- a/config.json +++ b/config.json @@ -1,8 +1,11 @@ { "menu_url": "https://redefinemeals.com/menu", - "order_deadline": "Wednesday 11:59 PM", + "order_deadline": "Thursday at 11:59 PM", "output_dir": "output", "orders_dir": "orders", + "bulk_discount_percent": 10, + "company_subsidy_percent": 50, + "google_client_id": "", "roster": [ {"name": "Example Employee", "email": "example@seahavenind.com"} ] diff --git a/functions/aggregate_orders/handler.py b/functions/aggregate_orders/handler.py index 2586d6a..897ad82 100644 --- a/functions/aggregate_orders/handler.py +++ b/functions/aggregate_orders/handler.py @@ -65,13 +65,18 @@ def lambda_handler(event, context): def build_summary(orders: list[dict], week: str) -> dict: - meal_totals = defaultdict(lambda: {"quantity": 0, "unit_price": 0}) + meal_totals = defaultdict( + lambda: {"quantity": 0, "bulk_price": 0, "employee_price": 0} + ) for order in orders: for item in order.get("items", []): name = item["name"] qty = int(item.get("quantity", 0)) meal_totals[name]["quantity"] += qty - meal_totals[name]["unit_price"] = float(item.get("price", 0)) + meal_totals[name]["bulk_price"] = float( + item.get("bulk_price", item.get("price", 0)) + ) + meal_totals[name]["employee_price"] = float(item.get("price", 0)) meals = [] for name, data in sorted(meal_totals.items()): @@ -79,8 +84,12 @@ def build_summary(orders: list[dict], week: str) -> dict: { "meal": name, "quantity": data["quantity"], - "unit_price": data["unit_price"], - "line_total": round(data["unit_price"] * data["quantity"], 2), + "unit_price": data["bulk_price"], + "employee_unit_price": data["employee_price"], + "line_total": round(data["bulk_price"] * data["quantity"], 2), + "employee_line_total": round( + data["employee_price"] * data["quantity"], 2 + ), } ) @@ -90,6 +99,7 @@ def build_summary(orders: list[dict], week: str) -> dict: "total_employees": len(orders), "total_meals": sum(m["quantity"] for m in meals), "grand_total": round(sum(m["line_total"] for m in meals), 2), + "employee_total": round(sum(m["employee_line_total"] for m in meals), 2), "meals": meals, } diff --git a/src/aggregator/aggregate.py b/src/aggregator/aggregate.py index 490ef32..292c066 100644 --- a/src/aggregator/aggregate.py +++ b/src/aggregator/aggregate.py @@ -41,12 +41,17 @@ def load_orders(week: str) -> list[dict]: def generate_order_summary(orders: list[dict]) -> dict: """Aggregate all meals across employees into a single order for Redefine.""" - meal_totals = defaultdict(lambda: {"quantity": 0, "unit_price": 0}) + meal_totals = defaultdict( + lambda: {"quantity": 0, "bulk_price": 0, "employee_price": 0} + ) for order in orders: for item in order.get("items", []): name = item["name"] meal_totals[name]["quantity"] += item.get("quantity", 0) - meal_totals[name]["unit_price"] = item.get("price", 0) + meal_totals[name]["bulk_price"] = item.get( + "bulk_price", item.get("price", 0) + ) + meal_totals[name]["employee_price"] = item.get("price", 0) summary = [] for name, data in sorted(meal_totals.items()): @@ -54,12 +59,17 @@ def generate_order_summary(orders: list[dict]) -> dict: { "meal": name, "quantity": data["quantity"], - "unit_price": data["unit_price"], - "line_total": round(data["unit_price"] * data["quantity"], 2), + "unit_price": data["bulk_price"], + "employee_unit_price": data["employee_price"], + "line_total": round(data["bulk_price"] * data["quantity"], 2), + "employee_line_total": round( + data["employee_price"] * data["quantity"], 2 + ), } ) grand_total = sum(s["line_total"] for s in summary) + employee_total = sum(s["employee_line_total"] for s in summary) total_meals = sum(s["quantity"] for s in summary) return { @@ -68,6 +78,7 @@ def generate_order_summary(orders: list[dict]) -> dict: "total_employees": len(orders), "total_meals": total_meals, "grand_total": round(grand_total, 2), + "employee_total": round(employee_total, 2), "meals": summary, } @@ -150,6 +161,10 @@ def main(): print(f"{meal['meal']:<45} {meal['quantity']:>4} ${meal['line_total']:>7.2f}") print("-" * 60) print(f"{'TOTAL':<45} {summary['total_meals']:>4} ${summary['grand_total']:>7.2f}") + if summary.get("employee_total") is not None and summary["employee_total"] != summary["grand_total"]: + print(f"{'PAYROLL DEDUCTIONS':<45} ${summary['employee_total']:>7.2f}") + subsidy = round(summary["grand_total"] - summary["employee_total"], 2) + print(f"{'COMPANY SUBSIDY':<45} ${subsidy:>7.2f}") print(f"\n{summary['total_employees']} employees ordered") print("\nFiles generated:") diff --git a/src/shared/shared/db.py b/src/shared/shared/db.py index 363ffb7..9557004 100644 --- a/src/shared/shared/db.py +++ b/src/shared/shared/db.py @@ -128,3 +128,19 @@ def put_roster(employees: list[dict]): "updated_at": datetime.now(EASTERN).isoformat(), } ) + + +def get_settings() -> dict: + resp = _get_table().get_item(Key={"PK": "CONFIG", "SK": "SETTINGS"}) + return resp.get("Item", {}) + + +def put_settings(settings: dict): + _get_table().put_item( + Item={ + "PK": "CONFIG", + "SK": "SETTINGS", + **_to_decimal(settings), + "updated_at": datetime.now(EASTERN).isoformat(), + } + )