import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { mydb } from "../../lib/mySupabase.ts"; import { corsHeaders, jsonResponse, errorResponse } from "../../lib/utils.ts"; import { validateAuth, hasPermission } from "../../lib/auth.ts"; /** * POST /appointments/no-show * Marcar consulta como no-show (paciente não compareceu) * * Body: * { * appointment_id: uuid, * reason?: string, * automatic_detection?: boolean * } * * Returns: * { * success: boolean, * appointment_id: uuid, * penalty_applied: boolean, * message: string * } */ serve(async (req) => { if (req.method === "OPTIONS") { return new Response("ok", { headers: corsHeaders() }); } try { const auth = await validateAuth(req); if (!auth) { return errorResponse("Não autorizado", 401); } if (req.method !== "POST") { return errorResponse("Method not allowed", 405); } const body = await req.json(); const { appointment_id, reason, automatic_detection } = body; // Apenas staff ou sistema pode marcar no-show if ( !hasPermission(auth.role, ["admin", "secretary", "doctor"]) && !automatic_detection ) { return errorResponse("Sem permissão", 403); } // Registrar no-show const noShowRes = await mydb .from("no_show_tracking") .insert({ appointment_id, patient_id: null, // Será preenchido na query doctor_id: null, marked_at: new Date().toISOString(), reason, automatic_detection: automatic_detection || false, }) .select(); if (noShowRes.error) { return errorResponse(noShowRes.error.message); } // Aplicar penalidade se necessário let penaltyApplied = false; // TODO: Implementar lógica de penalidade (reduzir pontos gamificação, etc) // Registrar em patient_journey await mydb.from("patient_journey").insert({ patient_id: null, event_type: "no_show", event_data: { appointment_id, reason }, points_earned: -5, // Penalidade de pontos }); // Audit log await mydb.from("audit_log").insert({ user_id: automatic_detection ? null : auth.userId, action: "mark_no_show", target_type: "appointment", target_id: appointment_id, payload: { reason, automatic: automatic_detection }, }); return jsonResponse({ success: true, appointment_id, penalty_applied: penaltyApplied, message: "Consulta marcada como no-show", }); } catch (error: unknown) { console.error("[no-show]", error); const err = error as Error; return errorResponse(err.message, 500); } });