173 lines
4.7 KiB
TypeScript
173 lines
4.7 KiB
TypeScript
import { Elysia, t } from "elysia";
|
|
import prisma from "../lib/prisma";
|
|
|
|
export const rawMaterialsRoute = new Elysia({ prefix: "/raw-materials" })
|
|
.get("/", async () => {
|
|
const rawMaterials = await prisma.rawMaterial.findMany({
|
|
orderBy: { name: "asc" },
|
|
});
|
|
return rawMaterials;
|
|
})
|
|
.get("/:id", async ({ params, status }) => {
|
|
const id = parseInt(params.id);
|
|
if (isNaN(id)) return status(400, { message: "Invalid ID" });
|
|
|
|
const rawMaterial = await prisma.rawMaterial.findUnique({
|
|
where: { id },
|
|
include: {
|
|
bomItems: {
|
|
include: {
|
|
productVariant: {
|
|
include: {
|
|
product: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
translations: {
|
|
select: { langCode: true, name: true }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!rawMaterial) return status(404, { message: "Raw material not found" });
|
|
|
|
const result = {
|
|
...rawMaterial,
|
|
bomItems: rawMaterial.bomItems.map((item) => {
|
|
const prod = item.productVariant?.product;
|
|
if (!prod) return item;
|
|
const thName = prod.translations?.find((t) => t.langCode === "th")?.name;
|
|
const fallbackName = prod.translations?.[0]?.name;
|
|
const resolvedName = prod.name || thName || fallbackName || `Product #${prod.id}`;
|
|
return {
|
|
...item,
|
|
productVariant: {
|
|
...item.productVariant,
|
|
product: {
|
|
...prod,
|
|
name: resolvedName,
|
|
}
|
|
}
|
|
};
|
|
})
|
|
};
|
|
|
|
return result;
|
|
|
|
})
|
|
.post("/bulk", async ({ body, status }) => {
|
|
try {
|
|
const items = Array.isArray(body) ? body : [body];
|
|
if (items.length === 0) {
|
|
return status(400, { message: "Payload must be a non-empty array" });
|
|
}
|
|
|
|
const results = await prisma.$transaction(async (tx) => {
|
|
const records = [];
|
|
for (const item of items) {
|
|
const name = String(item.name || "").trim();
|
|
if (!name) continue;
|
|
|
|
const unit = String(item.unit || "piece").trim() || "piece";
|
|
const rawPrice = item.pricePerUnit;
|
|
const pricePerUnit = typeof rawPrice === "string" ? (parseFloat(rawPrice) || 0) : Number(rawPrice) || 0;
|
|
|
|
const record = await tx.rawMaterial.upsert({
|
|
where: { name },
|
|
create: {
|
|
name,
|
|
unit,
|
|
pricePerUnit,
|
|
},
|
|
update: {
|
|
unit,
|
|
pricePerUnit,
|
|
},
|
|
});
|
|
records.push(record);
|
|
}
|
|
return records;
|
|
});
|
|
|
|
return status(200, {
|
|
success: true,
|
|
count: results.length,
|
|
items: results,
|
|
});
|
|
} catch (err: any) {
|
|
console.error("Bulk raw material import failed:", err);
|
|
return status(500, { message: "Failed to bulk import raw materials", error: err.message });
|
|
}
|
|
}, {
|
|
body: t.Array(
|
|
t.Object({
|
|
name: t.String(),
|
|
unit: t.Optional(t.String()),
|
|
pricePerUnit: t.Union([t.Number(), t.String()]),
|
|
})
|
|
),
|
|
detail: { tags: ["raw-materials"] }
|
|
})
|
|
.post("/", async ({ body, status }) => {
|
|
try {
|
|
const rawMaterial = await prisma.rawMaterial.create({
|
|
data: body,
|
|
});
|
|
return status(201, rawMaterial);
|
|
} catch (err) {
|
|
console.error(err);
|
|
return status(500, { message: "Failed to create raw material" });
|
|
}
|
|
}, {
|
|
body: t.Object({
|
|
name: t.String(),
|
|
unit: t.String(),
|
|
pricePerUnit: t.Number(),
|
|
}),
|
|
detail: { tags: ["raw-materials"] }
|
|
})
|
|
.put("/:id", async ({ params, body, status }) => {
|
|
const id = parseInt(params.id);
|
|
if (isNaN(id)) return status(400, { message: "Invalid ID" });
|
|
|
|
try {
|
|
const rawMaterial = await prisma.rawMaterial.update({
|
|
where: { id },
|
|
data: body,
|
|
});
|
|
return rawMaterial;
|
|
} catch (err) {
|
|
console.error(err);
|
|
return status(500, { message: "Failed to update raw material" });
|
|
}
|
|
}, {
|
|
body: t.Object({
|
|
name: t.String(),
|
|
unit: t.String(),
|
|
pricePerUnit: t.Number(),
|
|
}),
|
|
detail: { tags: ["raw-materials"] }
|
|
})
|
|
.delete("/:id", async ({ params, status }) => {
|
|
const id = parseInt(params.id);
|
|
if (isNaN(id)) return status(400, { message: "Invalid ID" });
|
|
|
|
try {
|
|
await prisma.rawMaterial.delete({
|
|
where: { id },
|
|
});
|
|
return { success: true };
|
|
} catch (err) {
|
|
console.error(err);
|
|
return status(500, { message: "Failed to delete raw material" });
|
|
}
|
|
}, {
|
|
detail: { tags: ["raw-materials"] }
|
|
});
|