mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
183fe0a93c
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
3.1 KiB
TypeScript
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" },
|
|
});
|
|
});
|