Changes
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
co-authored by
renee-png
parent
3d92e220e0
commit
0462ffb3ec
@@ -1271,6 +1271,89 @@ function ImportPage() {
|
||||
const chunkSize = 200;
|
||||
let inserted = 0;
|
||||
const inserted_rows: Row[] = [];
|
||||
|
||||
// INVOICES: special merge — match existing invoices by invoice_number
|
||||
// (preferred) or external_id and UPDATE only header fields. Subtotal,
|
||||
// total, tax, and amount_paid are left alone so totals stay = sum of
|
||||
// line items already attached from the time/expense imports.
|
||||
if (cfg.table === "invoices" && mapped.length > 0) {
|
||||
const numbers = mapped.map((r) => String(r.invoice_number ?? "")).filter(Boolean);
|
||||
const externalIds = mapped.map((r) => String(r.external_id ?? "")).filter(Boolean);
|
||||
const byNumber = new Map<string, string>();
|
||||
const byExt = new Map<string, string>();
|
||||
for (let k = 0; k < numbers.length; k += 500) {
|
||||
const slice = numbers.slice(k, k + 500);
|
||||
const { data } = await supabase
|
||||
.from("invoices")
|
||||
.select("id, invoice_number")
|
||||
.in("invoice_number", slice);
|
||||
for (const row of (data ?? []) as { id: string; invoice_number: string }[]) {
|
||||
byNumber.set(row.invoice_number, row.id);
|
||||
}
|
||||
}
|
||||
for (let k = 0; k < externalIds.length; k += 500) {
|
||||
const slice = externalIds.slice(k, k + 500);
|
||||
const { data } = await supabase
|
||||
.from("invoices")
|
||||
.select("id, external_id")
|
||||
.in("external_id", slice);
|
||||
for (const row of (data ?? []) as { id: string; external_id: string }[]) {
|
||||
byExt.set(row.external_id, row.id);
|
||||
}
|
||||
}
|
||||
|
||||
const HEADER_FIELDS = [
|
||||
"status", "issue_date", "due_date", "notes",
|
||||
"client_id", "case_id", "external_id", "invoice_number",
|
||||
] as const;
|
||||
const toUpdateInv: Array<{ id: string; payload: Row }> = [];
|
||||
const toInsertInv: Row[] = [];
|
||||
for (const r of mapped) {
|
||||
const num = r.invoice_number ? String(r.invoice_number) : "";
|
||||
const ext = r.external_id ? String(r.external_id) : "";
|
||||
const matchId = (num && byNumber.get(num)) || (ext && byExt.get(ext)) || null;
|
||||
if (matchId) {
|
||||
const payload: Row = {};
|
||||
for (const f of HEADER_FIELDS) {
|
||||
if (r[f] != null && r[f] !== "") payload[f] = r[f];
|
||||
}
|
||||
toUpdateInv.push({ id: matchId, payload });
|
||||
} else {
|
||||
toInsertInv.push(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (let k = 0; k < toUpdateInv.length; k += 50) {
|
||||
const slice = toUpdateInv.slice(k, k + 50);
|
||||
const results = await Promise.all(
|
||||
slice.map(({ id, payload }) =>
|
||||
supabase.from("invoices").update(payload as any).eq("id", id).select("*").single(),
|
||||
),
|
||||
);
|
||||
for (const result of results) {
|
||||
if (result.error) {
|
||||
errors.push(`Invoice merge update: ${result.error.message}`);
|
||||
} else if (result.data) {
|
||||
inserted += 1;
|
||||
inserted_rows.push(result.data as Row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let k = 0; k < toInsertInv.length; k += chunkSize) {
|
||||
const slice = toInsertInv.slice(k, k + chunkSize);
|
||||
const { data, error } = await supabase.from("invoices").insert(slice as any).select("*");
|
||||
if (error) errors.push(`Invoice merge insert: ${error.message}`);
|
||||
else if (data) {
|
||||
inserted += data.length;
|
||||
inserted_rows.push(...(data as Row[]));
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the generic chunk loop below for invoices.
|
||||
mapped.length = 0;
|
||||
}
|
||||
|
||||
for (let i = 0; i < mapped.length; i += chunkSize) {
|
||||
const chunk = mapped.slice(i, i + chunkSize);
|
||||
// Filter out rows missing the conflict column for upsert; insert plain
|
||||
|
||||
Reference in New Issue
Block a user