import { getOrderUpdateForDeliveryInvitationAction } from "../_shared/delivery-invitations.ts"; import { requireUuid } from "../_shared/security.ts"; import { createServiceClient } from "../_shared/chatbot.ts"; import { insertIntegrationEvent } from "../_shared/integration-events.ts"; import { getCorsHeaders, jsonResponse, readJsonBody, requireRateLimit, verifyInternalRequest, } from "../_shared/security.ts"; const MAX_BODY_BYTES = 16 * 1024; type ReportBody = { orderId?: string; result?: "delivered" | "problem"; note?: string; payload?: Record; }; Deno.serve(async (request) => { if (request.method === "OPTIONS") { const corsHeaders = getCorsHeaders(request, "integration"); return corsHeaders ? new Response("ok", { headers: corsHeaders }) : jsonResponse({ error: "Origin not allowed" }, 403); } if (request.method !== "POST") { return jsonResponse({ error: "Method not allowed" }, 405); } const corsHeaders = getCorsHeaders(request, "integration") || {}; try { const { body, rawBody } = await readJsonBody(request, { maxBytes: MAX_BODY_BYTES, }); await verifyInternalRequest(request, rawBody, { rawBody }); if (!body.orderId) { return jsonResponse({ error: "orderId is required" }, 400, corsHeaders); } try { requireUuid(body.orderId, "orderId"); } catch (e) { return jsonResponse({ ok: false, error: (e as Error).message }, 400, corsHeaders); } const supabase = createServiceClient(); await requireRateLimit(supabase, { scope: "delivery-report", key: body.orderId, maxCount: 10, windowSeconds: 600, blockSeconds: 1800, }); const { data: currentOrder, error: orderError } = await supabase .from("orders") .select("id, status, delivery_agreement_status") .eq("id", body.orderId) .single(); if (orderError) { throw orderError; } const isDelivered = body.result === "delivered"; const action = isDelivered ? "mark_delivered" : "mark_paid_storage"; const orderUpdate = getOrderUpdateForDeliveryInvitationAction(action); const nextStatus = isDelivered ? orderUpdate?.status || "Доставлен" : "Проблема доставки"; const { error: invitationError } = await supabase .from("delivery_invitations") .update({ state: isDelivered ? "delivered" : "paid_storage", ...(isDelivered ? { delivered_at: new Date().toISOString() } : { paid_storage_at: new Date().toISOString() }), }) .eq("order_id", body.orderId); if (invitationError) { throw invitationError; } const { error: updateError } = await supabase .from("orders") .update({ status: nextStatus, delivery_agreement_status: isDelivered ? "Подтверждено клиентом" : body.note || currentOrder.delivery_agreement_status || "Ошибка отправки", }) .eq("id", body.orderId); if (updateError) { throw updateError; } const { error: historyError } = await supabase.from("order_history").insert({ order_id: body.orderId, action: isDelivered ? "Подтверждение доставки" : "Фиксация проблемы доставки", old_status: currentOrder.status, new_status: isDelivered ? "Доставлен" : "Проблема доставки", metadata: { old_delivery_agreement_status: currentOrder.delivery_agreement_status, new_delivery_agreement_status: isDelivered ? "Подтверждено клиентом" : body.note || currentOrder.delivery_agreement_status || "Ошибка отправки", payload: body.payload || {}, }, }); if (historyError) { throw historyError; } await insertIntegrationEvent(supabase, { order_id: body.orderId, event_type: isDelivered ? "delivery_result_delivered" : "delivery_result_problem", direction: "internal", status: "success", payload: { result: body.result || null, note: body.note || null, payload: body.payload || {}, }, }); return jsonResponse( { ok: true, orderId: body.orderId, status: nextStatus, deliveryAgreementStatus: isDelivered ? "Подтверждено клиентом" : body.note || currentOrder.delivery_agreement_status || "Ошибка отправки", workflowStatus: nextStatus, }, 200, corsHeaders, ); } catch (error) { if (error instanceof Error && "status" in error) { const httpError = error as { status: number; message: string }; return jsonResponse({ ok: false, error: httpError.message }, httpError.status, corsHeaders); } return jsonResponse( { ok: false, error: error instanceof Error ? error.message : "Unexpected error", }, 500, corsHeaders, ); } });