import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.0"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", }; function addInterval(dateStr: string, freq: string): string { const d = new Date(dateStr + "T12:00:00"); switch (freq) { case "weekly": d.setDate(d.getDate() + 7); break; case "biweekly": d.setDate(d.getDate() + 14); break; case "monthly": d.setMonth(d.getMonth() + 1); break; case "quarterly": d.setMonth(d.getMonth() + 3); break; case "semiannual": d.setMonth(d.getMonth() + 6); break; case "annual": d.setFullYear(d.getFullYear() + 1); break; default: d.setMonth(d.getMonth() + 1); } return d.toISOString().slice(0, 10); } Deno.serve(async (req) => { if (req.method === "OPTIONS") return new Response("ok", { headers: corsHeaders }); const supabase = createClient( Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")! ); const today = new Date().toISOString().slice(0, 10); const { data: due, error } = await supabase .from("invoices") .select("*") .not("recurrence_frequency", "is", null) .lte("next_generation_date", today); if (error) { return new Response(JSON.stringify({ error: error.message }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" }, }); } let created = 0; const errors: string[] = []; for (const tmpl of due || []) { try { if (tmpl.recurrence_end_date && tmpl.next_generation_date > tmpl.recurrence_end_date) continue; const issueDate = tmpl.next_generation_date || today; const dueOffset = tmpl.due_date && tmpl.issue_date ? Math.round((new Date(tmpl.due_date).getTime() - new Date(tmpl.issue_date).getTime()) / 86400000) : 30; const newDue = new Date(issueDate + "T12:00:00"); newDue.setDate(newDue.getDate() + dueOffset); const { error: insErr } = await supabase.from("invoices").insert({ association_id: tmpl.association_id, vendor_name: tmpl.vendor_name, invoice_number: tmpl.invoice_number ? `${tmpl.invoice_number}-${issueDate}` : null, amount: tmpl.amount, status: "pending", issue_date: issueDate, due_date: newDue.toISOString().slice(0, 10), description: tmpl.description, category: tmpl.category, line_items: tmpl.line_items, rate: tmpl.rate, parent_invoice_id: tmpl.id, }); if (insErr) { errors.push(insErr.message); continue; } const next = addInterval(issueDate, tmpl.recurrence_frequency); const stop = tmpl.recurrence_end_date && next > tmpl.recurrence_end_date; await supabase.from("invoices").update({ next_generation_date: stop ? null : next, recurrence_frequency: stop ? null : tmpl.recurrence_frequency, }).eq("id", tmpl.id); created++; } catch (e) { errors.push(String(e)); } } return new Response(JSON.stringify({ created, errors }), { headers: { ...corsHeaders, "Content-Type": "application/json" }, }); });