feat(11-02): extend getAllServices with tags join (ServiceWithTags)
- Add ServiceWithTags type = Service & { tags: string[] }
- getAllServices() now left-joins tags scoped to entity_type=services
- Tags aggregated per service, ordered by service name then tag name
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
|||||||
offer_phase_services,
|
offer_phase_services,
|
||||||
quotes,
|
quotes,
|
||||||
leads,
|
leads,
|
||||||
|
tags,
|
||||||
} from "@/db/schema";
|
} from "@/db/schema";
|
||||||
import { eq, inArray, asc, isNull, sql, and } from "drizzle-orm";
|
import { eq, inArray, asc, isNull, sql, and } from "drizzle-orm";
|
||||||
import type {
|
import type {
|
||||||
@@ -356,11 +357,42 @@ export async function getClientFullDetail(id: string): Promise<ClientFullDetail
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAllServices(): Promise<Service[]> {
|
// ── ServiceWithTags — services + assigned tag names (Phase 11 database-view) ──
|
||||||
return db
|
|
||||||
.select()
|
export type ServiceWithTags = Service & { tags: string[] };
|
||||||
|
|
||||||
|
export async function getAllServices(): Promise<ServiceWithTags[]> {
|
||||||
|
const rows = await db
|
||||||
|
.select({
|
||||||
|
id: services.id,
|
||||||
|
name: services.name,
|
||||||
|
description: services.description,
|
||||||
|
unit_price: services.unit_price,
|
||||||
|
category: services.category,
|
||||||
|
active: services.active,
|
||||||
|
migrated_from: services.migrated_from,
|
||||||
|
migrated_id: services.migrated_id,
|
||||||
|
created_at: services.created_at,
|
||||||
|
tag_name: tags.name,
|
||||||
|
})
|
||||||
.from(services)
|
.from(services)
|
||||||
.orderBy(asc(services.name));
|
.leftJoin(
|
||||||
|
tags,
|
||||||
|
and(eq(tags.entity_type, "services"), eq(tags.entity_id, services.id))
|
||||||
|
)
|
||||||
|
.orderBy(asc(services.name), asc(tags.name));
|
||||||
|
|
||||||
|
const serviceMap = new Map<string, ServiceWithTags>();
|
||||||
|
for (const row of rows) {
|
||||||
|
const { tag_name, ...serviceFields } = row;
|
||||||
|
if (!serviceMap.has(row.id)) {
|
||||||
|
serviceMap.set(row.id, { ...serviceFields, tags: [] });
|
||||||
|
}
|
||||||
|
if (tag_name) {
|
||||||
|
serviceMap.get(row.id)!.tags.push(tag_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(serviceMap.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── ProjectWithPayments — used by /admin/projects list ───────────────────────
|
// ── ProjectWithPayments — used by /admin/projects list ───────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user