mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Accounting: Sales Receipts, COA sync to dashboard, vendor-expense recognition
- Add Sales Receipts page (dashboard/accounting/sales-receipts): records a cash sale (name, address, income account, price, qty) — deposits and books income in one step via a transaction. New accounting.sales_receipts table. - Sync chart of accounts to the accounting dashboard: mirror accounting.accounts into public.chart_of_accounts for platform associations (one-way, same id) so Bill Approvals and every COA consumer use the dashboard's accounts. Legacy rows hidden; Bill Approvals made system-aware. - Vendor-expense recognition: a vendor payment with no bill now books the expense directly (Dr Expense / Cr Bank) on the payment date instead of going to A/P; payments against open bills still clear A/P (applied FIFO). Backfill reclassifies unbilled payments stuck in A/P. Expense Summary report made GL-driven so it follows the same rule. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -172,8 +172,8 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
setBills([]);
|
||||
setApprovalsByBill({});
|
||||
const [aRes2, coaRes2, vRes2] = await Promise.all([
|
||||
supabase.from("associations").select("id, name").eq("status", "active").order("name"),
|
||||
supabase.from("chart_of_accounts").select("id, account_name, account_number, account_type").eq("account_type", "expense").order("account_number"),
|
||||
supabase.from("associations").select("id, name, accounting_system").eq("status", "active").order("name"),
|
||||
supabase.from("chart_of_accounts").select("id, account_name, account_number, account_type, accounting_system, association_id").eq("account_type", "expense").eq("is_active", true).order("account_number"),
|
||||
supabase.from("vendors").select("id, name, address, association_id, association_ids").eq("is_active", true).order("name"),
|
||||
]);
|
||||
setAssociations(aRes2.data || []);
|
||||
@@ -201,8 +201,8 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
if (data.length < PAGE) break;
|
||||
}
|
||||
const [aRes, coaRes, vRes] = await Promise.all([
|
||||
supabase.from("associations").select("id, name").eq("status", "active").order("name"),
|
||||
supabase.from("chart_of_accounts").select("id, account_name, account_number, account_type").eq("account_type", "expense").order("account_number"),
|
||||
supabase.from("associations").select("id, name, accounting_system").eq("status", "active").order("name"),
|
||||
supabase.from("chart_of_accounts").select("id, account_name, account_number, account_type, accounting_system, association_id").eq("account_type", "expense").eq("is_active", true).order("account_number"),
|
||||
supabase.from("vendors").select("id, name, address, association_id, association_ids").eq("is_active", true).order("name"),
|
||||
]);
|
||||
|
||||
@@ -604,8 +604,17 @@ export default function BillApprovalsPage({ boardAssociationIds }: { boardAssoci
|
||||
return bill.status;
|
||||
};
|
||||
|
||||
const selectedSystem = associations.find((a: any) => a.id === form.association_id)?.accounting_system ?? null;
|
||||
const filteredAccounts = form.association_id
|
||||
? accounts.filter((a: any) => !a.association_id || a.association_id === form.association_id)
|
||||
? accounts.filter((a: any) => {
|
||||
// Platform associations use the accounts managed in the accounting
|
||||
// dashboard (synced into chart_of_accounts as accounting_system 'platform').
|
||||
if (selectedSystem === "platform") {
|
||||
return a.accounting_system === "platform" && a.association_id === form.association_id;
|
||||
}
|
||||
// Buildium / Zoho keep their existing scoping; never surface platform-only rows.
|
||||
return a.accounting_system !== "platform" && (!a.association_id || a.association_id === form.association_id);
|
||||
})
|
||||
: [];
|
||||
|
||||
const filteredVendors = form.association_id
|
||||
|
||||
Reference in New Issue
Block a user