From 9bbc077129c07c20706418b5f6d764dca93a94ca Mon Sep 17 00:00:00 2001 From: Ricardo Mancinas Date: Wed, 22 Jul 2026 20:55:28 -0700 Subject: [PATCH] Customers: sort nameless records last instead of first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 44 customers with no recoverable name render as "(SIN NOMBRE)", and ordering the list by name alone floated all of them to the top — "(" sorts before every letter — so the first two screens of the customer browser were nothing but placeholders. Small number, worst possible position. Adds customers.nameMissing, set by the transform and used as the primary sort key so those records land at the end of the list. Denormalized rather than computed in the query because the list is paginated in SQL, so the ordering has to be expressible as a column. Applied to the dev DB as an ALTER + UPDATE in place (no truncate), so the existing loaded data and its FKs were left alone. Co-Authored-By: Claude Opus 4.8 --- apps/api/src/customers/customers.service.ts | 4 +++- migration/transform_customers.py | 5 ++++- packages/database/prisma/schema.prisma | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/api/src/customers/customers.service.ts b/apps/api/src/customers/customers.service.ts index de9a1e1..a31c57c 100644 --- a/apps/api/src/customers/customers.service.ts +++ b/apps/api/src/customers/customers.service.ts @@ -41,7 +41,9 @@ export class CustomersService { where, skip: (page - 1) * pageSize, take: pageSize, - orderBy: { name: "asc" }, + // Nameless records last: ordering by name alone floats every + // "(SIN NOMBRE)" to the top, since "(" sorts before every letter. + orderBy: [{ nameMissing: "asc" }, { name: "asc" }], select: { id: true, name: true, diff --git a/migration/transform_customers.py b/migration/transform_customers.py index 1d49a8e..804c750 100644 --- a/migration/transform_customers.py +++ b/migration/transform_customers.py @@ -170,6 +170,7 @@ def customer_from_utilities(row, name_index) -> dict: id=str(uuid.uuid4()), name=name, nameSource=name_source, + nameMissing=int(name == NO_NAME), addressLine1=s(row["direccion"]), addressLine2=s(row["colonia"]), city=s(row["ciudad"]), @@ -197,6 +198,7 @@ def customer_from_insurance(row, name_index) -> dict: id=str(uuid.uuid4()), name=name, nameSource=name_source, + nameMissing=int(name == NO_NAME), addressLine1=s(row["direccion_1"]), addressLine2=s(row["direccion_2"]), city=s(row["ciudad"]), @@ -219,7 +221,7 @@ def customer_from_insurance(row, name_index) -> dict: _CUST_COLS = [ - "id", "name", "nameSource", "addressLine1", "addressLine2", "city", "state", "zipCode", + "id", "name", "nameSource", "nameMissing", "addressLine1", "addressLine2", "city", "state", "zipCode", "country", "phone", "mobile", "fax", "email", "notes", "identificationType", "identificationNumber", "identificationExpiration", "customerSince", "status", "feeAmount", "updatedAt", @@ -276,6 +278,7 @@ def main() -> None: if master["name"] == NO_NAME and ins_rec["name"] != NO_NAME: master["name"] = ins_rec["name"] master["nameSource"] = ins_rec["nameSource"] or "DATGRAL (seguros)" + master["nameMissing"] = 0 from_ins_side += 1 enrich.append((cust_id, ins_rec)) else: diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index bc81dac..94f30a9 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -55,6 +55,10 @@ model Customer { // recovered from a secondary table (see migration/transform_customers.py), // so staff can tell a reconstructed name from an original one. nameSource String? + // True when `name` is the "(SIN NOMBRE)" placeholder. Denormalized so lists + // can sort nameless records last — ordering by `name` alone puts them first, + // since "(" sorts before every letter. + nameMissing Boolean @default(false) addressLine1 String? addressLine2 String? city String?