false, 'error' => 'Method not allowed'], 405); } $people = normalizePeopleList(readJsonFile('people.json')); $actor = requireActivePerson($people); $actorId = (string) ($actor['id'] ?? ''); if ($actorId === '') { sendJson(['success' => false, 'error' => 'Invalid session'], 403); } $body = readJsonBody(); $id = isset($body['id']) ? trim((string) $body['id']) : ''; if ($id === '') { sendJson(['success' => false, 'error' => 'id is required'], 400); } $rawChores = normalizeChoresList(readJsonFile('chores.json')); $chores = migrateAllChores($rawChores, $people); $idx = findChoreIndexById($chores, $id); if ($idx === null) { sendJson(['success' => false, 'error' => 'Chore not found'], 404); } $row = $chores[$idx]; if (($row['status'] ?? '') !== 'active') { sendJson(['success' => false, 'error' => 'This chore is not active'], 400); } $assignees = $row['assignee_ids'] ?? []; if (!is_array($assignees) || !in_array($actorId, $assignees, true)) { sendJson(['success' => false, 'error' => 'Only assignees can mark this chore complete'], 403); } if (!empty($row['pending_submission']) && is_array($row['pending_submission'])) { sendJson(['success' => false, 'error' => 'This chore is already waiting for approval'], 400); } $note = isset($body['note']) ? trim((string) $body['note']) : ''; $row['pending_submission'] = [ 'submitted_at' => gmdate('c'), 'submitted_by' => $actorId, 'note' => $note, ]; $chores[$idx] = migrateLegacyChoreRow($row, $people); if (!writeJsonFile('chores.json', $chores)) { sendJson(['success' => false, 'error' => 'Failed to save chores'], 500); } sendJson(['success' => true]);