- Item CRUD: getAllItems with category join, getById, create, update, delete - Category CRUD: getAll ordered by name, create, update, delete with reassignment - Totals: per-category aggregates and global totals via SQL SUM/COUNT - All 20 service tests passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
77 lines
1.7 KiB
TypeScript
77 lines
1.7 KiB
TypeScript
import { eq, asc } from "drizzle-orm";
|
|
import { categories, items } from "../../db/schema.ts";
|
|
import { db as prodDb } from "../../db/index.ts";
|
|
|
|
type Db = typeof prodDb;
|
|
|
|
export function getAllCategories(db: Db = prodDb) {
|
|
return db.select().from(categories).orderBy(asc(categories.name)).all();
|
|
}
|
|
|
|
export function createCategory(
|
|
db: Db = prodDb,
|
|
data: { name: string; emoji?: string },
|
|
) {
|
|
return db
|
|
.insert(categories)
|
|
.values({
|
|
name: data.name,
|
|
...(data.emoji ? { emoji: data.emoji } : {}),
|
|
})
|
|
.returning()
|
|
.get();
|
|
}
|
|
|
|
export function updateCategory(
|
|
db: Db = prodDb,
|
|
id: number,
|
|
data: { name?: string; emoji?: string },
|
|
) {
|
|
const existing = db
|
|
.select({ id: categories.id })
|
|
.from(categories)
|
|
.where(eq(categories.id, id))
|
|
.get();
|
|
|
|
if (!existing) return null;
|
|
|
|
return db
|
|
.update(categories)
|
|
.set(data)
|
|
.where(eq(categories.id, id))
|
|
.returning()
|
|
.get();
|
|
}
|
|
|
|
export function deleteCategory(
|
|
db: Db = prodDb,
|
|
id: number,
|
|
): { success: boolean; error?: string } {
|
|
// Guard: cannot delete Uncategorized (id=1)
|
|
if (id === 1) {
|
|
return { success: false, error: "Cannot delete the Uncategorized category" };
|
|
}
|
|
|
|
// Check if category exists
|
|
const existing = db
|
|
.select({ id: categories.id })
|
|
.from(categories)
|
|
.where(eq(categories.id, id))
|
|
.get();
|
|
|
|
if (!existing) {
|
|
return { success: false, error: "Category not found" };
|
|
}
|
|
|
|
// Reassign items to Uncategorized (id=1), then delete
|
|
// Use a transaction for atomicity
|
|
db.update(items)
|
|
.set({ categoryId: 1 })
|
|
.where(eq(items.categoryId, id))
|
|
.run();
|
|
|
|
db.delete(categories).where(eq(categories.id, id)).run();
|
|
|
|
return { success: true };
|
|
}
|