Files
2026-06-01 20:19:26 -04:00

90 lines
3.1 KiB
TypeScript

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" },
});
});