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,
|
||||
quotes,
|
||||
leads,
|
||||
tags,
|
||||
} from "@/db/schema";
|
||||
import { eq, inArray, asc, isNull, sql, and } from "drizzle-orm";
|
||||
import type {
|
||||
@@ -356,11 +357,42 @@ export async function getClientFullDetail(id: string): Promise<ClientFullDetail
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAllServices(): Promise<Service[]> {
|
||||
return db
|
||||
.select()
|
||||
// ── ServiceWithTags — services + assigned tag names (Phase 11 database-view) ──
|
||||
|
||||
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)
|
||||
.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 ───────────────────────
|
||||
|
||||
Reference in New Issue
Block a user