From 0d7d39542eb34ce43795e520505f22a11d125248 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 18:02:02 +0000 Subject: [PATCH 1/3] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/settings.import.tsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/routes/settings.import.tsx b/src/routes/settings.import.tsx index e0caa53..9990cbf 100644 --- a/src/routes/settings.import.tsx +++ b/src/routes/settings.import.tsx @@ -287,15 +287,9 @@ const IMPORTERS: ImporterConfig[] = [ const bm = String(r.billing_method).toLowerCase(); r.billing_method = bm.includes("flat") ? "flat" : bm.includes("contingency") ? "contingency" : bm.includes("hour") ? "hourly" : null; } - // Generate a collision-free case number when none was provided. - // Uses crypto.randomUUID so simultaneous rows in the same batch never collide. - if (!r.case_number || !String(r.case_number).trim()) { - const uid = (typeof crypto !== "undefined" && "randomUUID" in crypto) - ? crypto.randomUUID().slice(0, 8).toUpperCase() - : `${Date.now().toString(36)}${Math.floor(Math.random() * 1e6).toString(36)}`.toUpperCase(); - r.case_number = `CASE-${uid}`; - } - if (!r.title) r.title = r.case_number; + // Leave case_number blank when missing — assigned in a sequential + // "YYYY-####" pass before insert (see below). Do not synthesize title + // from case_number; preserve the imported matter name as-is. return r; }, postInsert: (rows, ctx) => { From dd0ce5dbe937e740083fac1e9e131995e5ad2cec Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 18:02:12 +0000 Subject: [PATCH 2/3] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/settings.import.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/settings.import.tsx b/src/routes/settings.import.tsx index 9990cbf..b96df37 100644 --- a/src/routes/settings.import.tsx +++ b/src/routes/settings.import.tsx @@ -188,7 +188,7 @@ const IMPORTERS: ImporterConfig[] = [ description: "Matters / cases linked to a client.", table: "cases", conflict: "external_id", - required: ["case_number", "title"], + required: ["title"], aliases: { // Identifiers id: "external_id", caseid: "external_id", externalid: "external_id", mycaseid: "external_id", From 18978132053f525cd8cdc25c1877eda63894e02b Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 18:02:25 +0000 Subject: [PATCH 3/3] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/settings.import.tsx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/routes/settings.import.tsx b/src/routes/settings.import.tsx index b96df37..2eca362 100644 --- a/src/routes/settings.import.tsx +++ b/src/routes/settings.import.tsx @@ -1055,6 +1055,31 @@ function ImportPage() { return; } + // For cases: assign sequential "YYYY-####" numbers to any row missing a + // case_number, continuing from the highest existing number for the year. + if (cfg.table === "cases") { + const year = new Date().getFullYear(); + const prefix = `${year}-`; + const { data: existing } = await supabase + .from("cases") + .select("case_number") + .like("case_number", `${prefix}%`); + let maxSeq = 0; + for (const row of (existing ?? []) as Array<{ case_number: string | null }>) { + const m = /^(\d{4})-(\d+)$/.exec(String(row.case_number ?? "")); + if (m && m[1] === String(year)) { + const n = parseInt(m[2], 10); + if (Number.isFinite(n) && n > maxSeq) maxSeq = n; + } + } + for (const r of mapped) { + if (!r.case_number || !String(r.case_number).trim()) { + maxSeq += 1; + r.case_number = `${prefix}${String(maxSeq).padStart(4, "0")}`; + } + } + } + // Batch upsert in chunks of 200 const chunkSize = 200; let inserted = 0;