feat(inventory): matlager-hantering – sök, plats-filter, markera flera, massradering

- API: POST /v1/inventory/bulk-delete (mjuk radering, ägar-kontroll, correction-tx)
- Mobil: "Ditt kök" görs om till hanteringsvy – sök, filter Kyl/Frys/Skafferi,
  sortering på plats+namn, markera flera (som mejlklient), Ta bort valda / Töm listan
- Hem: "+N till" blir klickbar och tar dig till Ditt kök
This commit is contained in:
Claude
2026-08-18 15:22:59 +00:00
parent 684743ae95
commit 610910ccf0
3 changed files with 216 additions and 72 deletions
+53 -1
View File
@@ -1,5 +1,5 @@
import type { FastifyInstance } from "fastify";
import { and, desc, eq, gt, ilike, isNull, or, sql } from "drizzle-orm";
import { and, desc, eq, gt, ilike, inArray, isNull, or, sql } from "drizzle-orm";
import { schema } from "@app/database";
import {
createInventoryItemInputSchema,
@@ -603,6 +603,58 @@ export async function inventoryRoutes(app: FastifyInstance) {
.where(eq(schema.inventoryItems.id, id));
return { ok: true };
});
// Massradering: markera flera eller töm en hel vy. Mjuk radering som ovan.
app.post("/v1/inventory/bulk-delete", auth, async (req) => {
const body = req.body as { ids?: unknown };
const ids = Array.isArray(body?.ids)
? body.ids.filter((x): x is string => typeof x === "string").slice(0, 1000)
: [];
if (ids.length === 0) throw errors.badRequest("ids saknas.");
const householdId = await requireActiveHousehold(app.db, req.userId);
const owned = await app.db
.select({
id: schema.inventoryItems.id,
quantity: schema.inventoryItems.quantity,
unit: schema.inventoryItems.unit,
})
.from(schema.inventoryItems)
.where(
and(
inArray(schema.inventoryItems.id, ids),
eq(schema.inventoryItems.householdId, householdId),
isNull(schema.inventoryItems.depletedAt),
),
);
if (owned.length === 0) return { ok: true, deleted: 0 };
const corrections = owned
.filter((i) => i.quantity > 0)
.map((i) => ({
householdId,
inventoryItemId: i.id,
type: "correction" as const,
quantityDelta: -i.quantity,
unit: i.unit,
actorUserId: req.userId,
note: "Massradering av användare",
}));
if (corrections.length > 0) {
await app.db.insert(schema.inventoryTransactions).values(corrections);
}
await app.db
.update(schema.inventoryItems)
.set({ quantity: 0, depletedAt: new Date(), updatedAt: new Date() })
.where(
and(
inArray(
schema.inventoryItems.id,
owned.map((i) => i.id),
),
eq(schema.inventoryItems.householdId, householdId),
),
);
return { ok: true, deleted: owned.length };
});
}
async function getOwnedItem(app: FastifyInstance, itemId: string, userId: string) {