Files
lunarfront-app/packages/backend/src/services/lookup.service.ts
Ryan Moon d36c6f7135 Remove multi-tenant company_id scoping from entire codebase
Drop company_id column from all 22 domain tables via migration.
Remove companyId from JWT payload, auth plugins, all service method
signatures (~215 occurrences), all route handlers (~105 occurrences),
test runner, test suites, and frontend auth store/types.

The company table stays as store settings (name, timezone). Tenant
isolation in a SaaS deployment would be at the database level (one
DB per customer) not the application level.

All 107 API tests pass. Zero TSC errors across all packages.
2026-03-29 14:58:33 -05:00

114 lines
3.1 KiB
TypeScript

import { eq } from 'drizzle-orm'
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'
import { ForbiddenError } from '../lib/errors.js'
import {
inventoryUnitStatuses,
itemConditions,
SYSTEM_UNIT_STATUSES,
SYSTEM_ITEM_CONDITIONS,
} from '../db/schema/lookups.js'
import type { LookupCreateInput, LookupUpdateInput } from '@forte/shared/schemas'
function createLookupService(
table: typeof inventoryUnitStatuses | typeof itemConditions,
systemSeeds: ReadonlyArray<{ slug: string; name: string; description: string; sortOrder: number }>,
) {
return {
async seedDefaults(db: PostgresJsDatabase<any>) {
const existing = await db
.select()
.from(table)
.where(eq(table.isSystem, true))
.limit(1)
if (existing.length > 0) return // already seeded
await db.insert(table).values(
systemSeeds.map((seed) => ({
...seed,
isSystem: true,
})),
)
},
async list(db: PostgresJsDatabase<any>) {
return db
.select()
.from(table)
.where(eq(table.isActive, true))
.orderBy(table.sortOrder)
},
async getBySlug(db: PostgresJsDatabase<any>, slug: string) {
const [row] = await db
.select()
.from(table)
.where(eq(table.slug, slug))
.limit(1)
return row ?? null
},
async create(db: PostgresJsDatabase<any>, input: LookupCreateInput) {
const [row] = await db
.insert(table)
.values({
name: input.name,
slug: input.slug,
description: input.description,
sortOrder: input.sortOrder,
isSystem: false,
})
.returning()
return row
},
async update(db: PostgresJsDatabase<any>, id: string, input: LookupUpdateInput) {
// Prevent modifying system rows' slug or system flag
const existing = await db
.select()
.from(table)
.where(eq(table.id, id))
.limit(1)
if (!existing[0]) return null
if (existing[0].isSystem && input.isActive === false) {
throw new ForbiddenError('Cannot deactivate a system status')
}
const [row] = await db
.update(table)
.set(input)
.where(eq(table.id, id))
.returning()
return row ?? null
},
async delete(db: PostgresJsDatabase<any>, id: string) {
const existing = await db
.select()
.from(table)
.where(eq(table.id, id))
.limit(1)
if (!existing[0]) return null
if (existing[0].isSystem) {
throw new ForbiddenError('Cannot delete a system status')
}
const [row] = await db
.delete(table)
.where(eq(table.id, id))
.returning()
return row ?? null
},
async validateSlug(db: PostgresJsDatabase<any>, slug: string): Promise<boolean> {
const row = await this.getBySlug(db, slug)
return row !== null && row.isActive
},
}
}
export const UnitStatusService = createLookupService(inventoryUnitStatuses, SYSTEM_UNIT_STATUSES)
export const ItemConditionService = createLookupService(itemConditions, SYSTEM_ITEM_CONDITIONS)