Files
GearBox/src/server/services/item.service.ts
Jean-Luc Makiola fb925a9dce
All checks were successful
CI / ci (push) Successful in 24s
CI / ci (pull_request) Successful in 25s
CI / e2e (push) Successful in 1m3s
CI / e2e (pull_request) Successful in 1m1s
fix: include quantity in getAllItems select, createItem values, and updateItem type
Quantity was missing from three places in item.service.ts:
- getAllItems didn't select it (API returned undefined)
- createItem didn't pass it to insert (always used DB default of 1)
- updateItem type didn't include it (silently stripped from updates)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 19:57:25 +02:00

142 lines
3.2 KiB
TypeScript

import { eq } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts";
import { categories, items } from "../../db/schema.ts";
import type { CreateItem } from "../../shared/types.ts";
type Db = typeof prodDb;
export function getAllItems(db: Db = prodDb) {
return db
.select({
id: items.id,
name: items.name,
weightGrams: items.weightGrams,
priceCents: items.priceCents,
quantity: items.quantity,
categoryId: items.categoryId,
notes: items.notes,
productUrl: items.productUrl,
imageFilename: items.imageFilename,
imageSourceUrl: items.imageSourceUrl,
createdAt: items.createdAt,
updatedAt: items.updatedAt,
categoryName: categories.name,
categoryIcon: categories.icon,
})
.from(items)
.innerJoin(categories, eq(items.categoryId, categories.id))
.all();
}
export function getItemById(db: Db = prodDb, id: number) {
return (
db
.select({
id: items.id,
name: items.name,
weightGrams: items.weightGrams,
priceCents: items.priceCents,
categoryId: items.categoryId,
notes: items.notes,
productUrl: items.productUrl,
imageFilename: items.imageFilename,
imageSourceUrl: items.imageSourceUrl,
createdAt: items.createdAt,
updatedAt: items.updatedAt,
})
.from(items)
.where(eq(items.id, id))
.get() ?? null
);
}
export function createItem(
db: Db = prodDb,
data: Partial<CreateItem> & {
name: string;
categoryId: number;
imageFilename?: string;
},
) {
return db
.insert(items)
.values({
name: data.name,
weightGrams: data.weightGrams ?? null,
priceCents: data.priceCents ?? null,
quantity: data.quantity ?? 1,
categoryId: data.categoryId,
notes: data.notes ?? null,
productUrl: data.productUrl ?? null,
imageFilename: data.imageFilename ?? null,
imageSourceUrl: data.imageSourceUrl ?? null,
})
.returning()
.get();
}
export function updateItem(
db: Db = prodDb,
id: number,
data: Partial<{
name: string;
weightGrams: number;
priceCents: number;
quantity: number;
categoryId: number;
notes: string;
productUrl: string;
imageFilename: string;
imageSourceUrl: string;
}>,
) {
// Check if item exists first
const existing = db
.select({ id: items.id })
.from(items)
.where(eq(items.id, id))
.get();
if (!existing) return null;
return db
.update(items)
.set({ ...data, updatedAt: new Date() })
.where(eq(items.id, id))
.returning()
.get();
}
export function duplicateItem(db: Db = prodDb, id: number) {
const source = db.select().from(items).where(eq(items.id, id)).get();
if (!source) return null;
return db
.insert(items)
.values({
name: `${source.name} (copy)`,
weightGrams: source.weightGrams,
priceCents: source.priceCents,
categoryId: source.categoryId,
notes: source.notes,
productUrl: source.productUrl,
imageFilename: source.imageFilename,
imageSourceUrl: source.imageSourceUrl,
quantity: source.quantity,
})
.returning()
.get();
}
export function deleteItem(db: Db = prodDb, id: number) {
// Get item first (for image cleanup info)
const item = db.select().from(items).where(eq(items.id, id)).get();
if (!item) return null;
db.delete(items).where(eq(items.id, id)).run();
return item;
}