false, 'error' => 'Method not allowed'], 405); } $people = normalizePeopleList(readJsonFile('people.json')); requireActivePerson($people); $body = readJsonBody(); $storeId = isset($body['storeId']) ? trim((string) $body['storeId']) : ''; $itemId = isset($body['itemId']) ? trim((string) $body['itemId']) : ''; $purchased = !empty($body['purchased']); if ($storeId === '' || $itemId === '') { sendJson(['success' => false, 'error' => 'storeId and itemId are required'], 400); } $lists = normalizeGroceryLists(readJsonFile('grocery_lists.json')); $items = $lists['byStore'][$storeId] ?? []; $idx = null; foreach ($items as $i => $it) { if (($it['id'] ?? '') === $itemId) { $idx = $i; break; } } if ($idx === null) { sendJson(['success' => false, 'error' => 'Item not found'], 404); } $row = $items[$idx]; $catalog = normalizeCatalogList(readJsonFile('grocery_catalog.json')); if ($purchased) { $row['status'] = 'purchased'; $row['purchasedAt'] = gmdate('c'); $cid = $row['catalogId'] ?? null; if (is_string($cid) && $cid !== '') { foreach ($catalog as $ci => $c) { if (($c['id'] ?? '') === $cid) { $catalog[$ci]['lastPurchaseAt'] = gmdate('c'); $days = max(0, (int) ($row['recurringIntervalDays'] ?? 0)); if ($days > 0) { $catalog[$ci]['recurringIntervalDays'] = $days; $catalog[$ci]['nextDueDate'] = gmdate('Y-m-d', strtotime('+' . $days . ' days')); } break; } } } } else { $row['status'] = 'active'; $row['purchasedAt'] = null; } $row = normalizeGroceryLineItem($row); $items[$idx] = $row; $lists['byStore'][$storeId] = $items; if (!writeJsonFile('grocery_catalog.json', $catalog)) { sendJson(['success' => false, 'error' => 'Failed to save catalog'], 500); } if (!writeJsonFile('grocery_lists.json', $lists)) { sendJson(['success' => false, 'error' => 'Failed to save grocery list'], 500); } sendJson(['success' => true]);