58 lines
3.7 KiB
TypeScript
58 lines
3.7 KiB
TypeScript
import type { FastifyInstance } from "fastify";
|
|
import { eq, and, sql } from "drizzle-orm";
|
|
import { offers as offersTable } from "@sankofa/schema";
|
|
|
|
export async function offersRoutes(app: FastifyInstance) {
|
|
const db = app.db;
|
|
const listSchema = { querystring: { type: "object", properties: { limit: { type: "integer" }, offset: { type: "integer" } } } };
|
|
app.get("/", { schema: listSchema }, async (req, reply) => {
|
|
const orgId = app.orgId(req);
|
|
const vid = app.vendorId(req);
|
|
const limit = Math.min(Number((req.query as { limit?: number }).limit) || 50, 100);
|
|
const offset = Number((req.query as { offset?: number }).offset) || 0;
|
|
const conditions = [eq(offersTable.orgId, orgId)] as ReturnType<typeof eq>[];
|
|
if (vid) conditions.push(eq(offersTable.vendorId, vid));
|
|
const list = await db.select().from(offersTable).where(and(...conditions)).limit(limit).offset(offset);
|
|
const [{ total }] = await db.select({ total: sql<number>`count(*)::int` }).from(offersTable).where(and(...conditions));
|
|
return reply.send({ data: list, total });
|
|
});
|
|
app.get<{ Params: { id: string } }>("/:id", async (req, reply) => {
|
|
const orgId = app.orgId(req);
|
|
const vid = app.vendorId(req);
|
|
const conditions = [eq(offersTable.id, req.params.id), eq(offersTable.orgId, orgId)] as ReturnType<typeof eq>[];
|
|
if (vid) conditions.push(eq(offersTable.vendorId, vid));
|
|
const [row] = await db.select().from(offersTable).where(and(...conditions));
|
|
if (!row) return reply.notFound();
|
|
return reply.send(row);
|
|
});
|
|
app.post<{ Body: { vendorId?: string; sku?: string; mpn?: string; quantity: number; unitPrice: string; incoterms?: string; leadTimeDays?: number; countryOfOrigin?: string; condition?: string; warranty?: string; evidenceRefs?: { key: string; hash?: string }[] } }>("/", async (req, reply) => {
|
|
const orgId = app.orgId(req);
|
|
const vid = app.vendorId(req);
|
|
const vendorId = vid ?? req.body.vendorId ?? null;
|
|
if (!vendorId) throw app.httpErrors.badRequest("vendorId required (or login as vendor user)");
|
|
const [inserted] = await db.insert(offersTable).values({
|
|
orgId, vendorId, sku: req.body.sku ?? null, mpn: req.body.mpn ?? null, quantity: req.body.quantity, unitPrice: req.body.unitPrice,
|
|
incoterms: req.body.incoterms ?? null, leadTimeDays: req.body.leadTimeDays ?? null, countryOfOrigin: req.body.countryOfOrigin ?? null, condition: req.body.condition ?? null, warranty: req.body.warranty ?? null, evidenceRefs: req.body.evidenceRefs ?? null,
|
|
}).returning();
|
|
return reply.code(201).send(inserted);
|
|
});
|
|
app.patch<{ Params: { id: string }; Body: Partial<{ sku: string; mpn: string; quantity: number; unitPrice: string; status: string; evidenceRefs: { key: string; hash?: string }[] }> }>("/:id", async (req, reply) => {
|
|
const orgId = app.orgId(req);
|
|
const vid = app.vendorId(req);
|
|
const conditions = [eq(offersTable.id, req.params.id), eq(offersTable.orgId, orgId)] as ReturnType<typeof eq>[];
|
|
if (vid) conditions.push(eq(offersTable.vendorId, vid));
|
|
const [updated] = await db.update(offersTable).set({ ...req.body, updatedAt: new Date() }).where(and(...conditions)).returning();
|
|
if (!updated) return reply.notFound();
|
|
return reply.send(updated);
|
|
});
|
|
app.delete<{ Params: { id: string } }>("/:id", async (req, reply) => {
|
|
const orgId = app.orgId(req);
|
|
const vid = app.vendorId(req);
|
|
const conditions = [eq(offersTable.id, req.params.id), eq(offersTable.orgId, orgId)] as ReturnType<typeof eq>[];
|
|
if (vid) conditions.push(eq(offersTable.vendorId, vid));
|
|
const [deleted] = await db.delete(offersTable).where(and(...conditions)).returning({ id: offersTable.id });
|
|
if (!deleted) return reply.notFound();
|
|
return reply.code(204).send();
|
|
});
|
|
}
|