Files
lunarfront-app/packages/backend/src/services/inventory.service.ts
Ryan Moon 77a3a6baa9 Add categories and suppliers with CRUD routes
- category table with hierarchical parent_id, sort ordering, soft-delete
- supplier table with contact info, account number, payment terms
- CRUD routes for both with search on suppliers
- Zod validation schemas in @forte/shared
- Products will link to suppliers via join table (many-to-many)
- 26 tests passing
2026-03-27 18:07:46 -05:00

110 lines
3.4 KiB
TypeScript

import { eq, and, ilike } from 'drizzle-orm'
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'
import { categories, suppliers } from '../db/schema/inventory.js'
import type {
CategoryCreateInput,
CategoryUpdateInput,
SupplierCreateInput,
SupplierUpdateInput,
} from '@forte/shared/schemas'
export const CategoryService = {
async create(db: PostgresJsDatabase, companyId: string, input: CategoryCreateInput) {
const [category] = await db
.insert(categories)
.values({ companyId, ...input })
.returning()
return category
},
async getById(db: PostgresJsDatabase, companyId: string, id: string) {
const [category] = await db
.select()
.from(categories)
.where(and(eq(categories.id, id), eq(categories.companyId, companyId)))
.limit(1)
return category ?? null
},
async list(db: PostgresJsDatabase, companyId: string) {
return db
.select()
.from(categories)
.where(and(eq(categories.companyId, companyId), eq(categories.isActive, true)))
.orderBy(categories.sortOrder)
},
async update(db: PostgresJsDatabase, companyId: string, id: string, input: CategoryUpdateInput) {
const [category] = await db
.update(categories)
.set({ ...input, updatedAt: new Date() })
.where(and(eq(categories.id, id), eq(categories.companyId, companyId)))
.returning()
return category ?? null
},
async softDelete(db: PostgresJsDatabase, companyId: string, id: string) {
const [category] = await db
.update(categories)
.set({ isActive: false, updatedAt: new Date() })
.where(and(eq(categories.id, id), eq(categories.companyId, companyId)))
.returning()
return category ?? null
},
}
export const SupplierService = {
async create(db: PostgresJsDatabase, companyId: string, input: SupplierCreateInput) {
const [supplier] = await db
.insert(suppliers)
.values({ companyId, ...input })
.returning()
return supplier
},
async getById(db: PostgresJsDatabase, companyId: string, id: string) {
const [supplier] = await db
.select()
.from(suppliers)
.where(and(eq(suppliers.id, id), eq(suppliers.companyId, companyId)))
.limit(1)
return supplier ?? null
},
async list(db: PostgresJsDatabase, companyId: string) {
return db
.select()
.from(suppliers)
.where(and(eq(suppliers.companyId, companyId), eq(suppliers.isActive, true)))
},
async search(db: PostgresJsDatabase, companyId: string, query: string) {
const pattern = `%${query}%`
return db
.select()
.from(suppliers)
.where(
and(eq(suppliers.companyId, companyId), eq(suppliers.isActive, true), ilike(suppliers.name, pattern)),
)
.limit(50)
},
async update(db: PostgresJsDatabase, companyId: string, id: string, input: SupplierUpdateInput) {
const [supplier] = await db
.update(suppliers)
.set({ ...input, updatedAt: new Date() })
.where(and(eq(suppliers.id, id), eq(suppliers.companyId, companyId)))
.returning()
return supplier ?? null
},
async softDelete(db: PostgresJsDatabase, companyId: string, id: string) {
const [supplier] = await db
.update(suppliers)
.set({ isActive: false, updatedAt: new Date() })
.where(and(eq(suppliers.id, id), eq(suppliers.companyId, companyId)))
.returning()
return supplier ?? null
},
}