mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Buildium -> Accounting: auto-provision companies + opening-balance migration
- buildium-sync now ensures every active association has an accounting company after syncing associations. Once it exists, the existing DB triggers flow units -> customers, owner ledger -> A/R + income, and bills -> A/P + expense into Accounting automatically (closing the gap where Buildium synced only the main dashboard, not Accounting). - New buildium-opening-balances function: fetches an association's Buildium GL trial balance as of a cutoff (default 2025-12-31, Accrual), maps GL accounts to accounting accounts (flagging bank accounts), rolls prior-year P&L into Retained Earnings, writes accounting.opening_balances, and posts the opening GL entry. Idempotent; service-role gated. Applied to 6 Buildium associations (opening balances + 2026 activity); all balance. New columns/data applied to the project directly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -656,7 +656,30 @@ Deno.serve(async (req) => {
|
||||
const { error } = await supabase.from("associations").upsert(upserts, { onConflict: "name", ignoreDuplicates: true });
|
||||
if (error) throw new Error(`Associations upsert failed: ${error.message}`);
|
||||
}
|
||||
results.associations = { fetched: associations.length, upserted: upserts.length };
|
||||
|
||||
// Ensure every active association has an accounting company. Once it exists,
|
||||
// the existing DB triggers automatically flow units -> customers, owner
|
||||
// ledger -> A/R + income, and bills -> A/P + expense into Accounting.
|
||||
// (Opening balances are a separate one-time migration: buildium-opening-balances.)
|
||||
let accountingCompaniesCreated = 0;
|
||||
try {
|
||||
const { data: activeAssocs } = await supabase.from("associations").select("id, name").eq("status", "active");
|
||||
const acctSchema = (supabase as any).schema("accounting");
|
||||
const { data: existingCompanies } = await acctSchema.from("companies").select("association_id");
|
||||
const haveCompany = new Set((existingCompanies || []).map((c: any) => c.association_id));
|
||||
const toCreate = (activeAssocs || []).filter((a: any) => a.id && !haveCompany.has(a.id));
|
||||
if (toCreate.length > 0) {
|
||||
const { error: compErr } = await acctSchema.from("companies").insert(
|
||||
toCreate.map((a: any) => ({ association_id: a.id, name: a.name || "Association", created_by: userId }))
|
||||
);
|
||||
if (compErr) console.warn(`Accounting company provisioning failed: ${compErr.message}`);
|
||||
else accountingCompaniesCreated = toCreate.length;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Accounting company provisioning error:", (e as Error)?.message);
|
||||
}
|
||||
|
||||
results.associations = { fetched: associations.length, upserted: upserts.length, accounting_companies_created: accountingCompaniesCreated };
|
||||
}
|
||||
|
||||
if (syncType === "all" || syncType === "units") {
|
||||
|
||||
Reference in New Issue
Block a user