fix(api): split week params and allow live menu nulls (DEV-289)

Menu and form-status take current or YYYY-WNN. Orders take YYYY-WNN or a
calendar date and reject current. Menu payloads may emit null menu_url,
calories, protein, and image_url.

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-09-22 00:13:16 +00:00
parent a51251b000
commit abe34de3d5
No known key found for this signature in database
3 changed files with 47 additions and 9 deletions

View file

@ -56,7 +56,7 @@ paths:
summary: Published menu for a week
security: []
parameters:
- $ref: "#/components/parameters/WeekPath"
- $ref: "#/components/parameters/MenuWeekPath"
responses:
"200":
description: Menu payload
@ -76,7 +76,7 @@ paths:
summary: Open or closed for a week
security: []
parameters:
- $ref: "#/components/parameters/WeekPath"
- $ref: "#/components/parameters/MenuWeekPath"
responses:
"200":
description: Form status
@ -128,7 +128,7 @@ paths:
security:
- portalCognito: []
parameters:
- $ref: "#/components/parameters/WeekPath"
- $ref: "#/components/parameters/OrderWeekPath"
responses:
"200":
description: Empty list when the caller has no order
@ -322,11 +322,19 @@ components:
name: X-Meals-Publish-Key
parameters:
WeekPath:
MenuWeekPath:
name: week
in: path
required: true
description: "`current`, `YYYY-WNN`, or for orders a calendar date that maps to a week"
description: "`current` or `YYYY-WNN`. Other values are 400."
schema:
type: string
minLength: 1
OrderWeekPath:
name: week
in: path
required: true
description: "`YYYY-WNN` or `YYYY-MM-DD`. `current` is 400."
schema:
type: string
minLength: 1
@ -373,9 +381,9 @@ components:
price:
type: number
calories:
type: [string, number]
type: [string, number, "null"]
protein:
type: [string, number]
type: [string, number, "null"]
description:
type: [string, "null"]
dietary_tags:
@ -383,7 +391,7 @@ components:
items:
type: string
image_url:
type: string
type: [string, "null"]
is_new:
type: boolean
@ -405,7 +413,7 @@ components:
scraped_at:
type: [string, "null"]
menu_url:
type: string
type: [string, "null"]
meal_count:
type: integer
meals:

View file

@ -24,6 +24,18 @@ def test_openapi_uses_redocly_recommended():
assert '"400":' not in roster
form_status = spec.split("/api/form-status/{week}:", 1)[1].split("\n /", 1)[0]
assert '"400":' in form_status
menu = spec.split("/api/menu/{week}:", 1)[1].split("\n /", 1)[0]
orders = spec.split("/api/orders/{week}:", 1)[1].split("\n /", 1)[0]
assert "MenuWeekPath" in menu
assert "MenuWeekPath" in form_status
assert "OrderWeekPath" in orders
assert "WeekPath" not in spec.split("components:", 1)[1].split("MenuWeekPath", 1)[0]
assert "`current` or `YYYY-WNN`" in spec
assert "`YYYY-WNN` or `YYYY-MM-DD`" in spec
meal = spec.split(" Meal:", 1)[1].split("\n MenuPayload:", 1)[0]
assert 'type: [string, number, "null"]' in meal
assert 'type: [string, "null"]' in meal
assert 'menu_url:\n type: [string, "null"]' in spec
assert "root: openapi.yaml" in redocly
assert '"openapi:lint"' in package
assert '"@redocly/cli": "2.52.1"' in package

View file

@ -2164,6 +2164,24 @@ def test_my_orders_empty_when_none(mock_looks_like, mock_portal, mock_get):
assert body == {"week": "2026-W36", "orders": []}
@patch("submit_order_handler.get_order")
@patch(
"submit_order_handler._verify_portal_token",
return_value={
"name": "Portal Employee",
"email": "portal.employee@seahavenind.com",
},
)
@patch("submit_order_handler.looks_like_cognito_token", return_value=True)
def test_my_orders_rejects_current_week(mock_looks_like, mock_portal, mock_get):
status, body = _parse_response(
submit_order_handler.lambda_handler(_orders_event(week="current"), None)
)
assert status == 400
assert "YYYY-WNN" in body["error"]
mock_get.assert_not_called()
def test_my_orders_requires_bearer():
status, body = _parse_response(
submit_order_handler.lambda_handler(_orders_event(token=""), None)