x
This commit is contained in:
1 parent
ae3799d8ce
commit
0341b30b6d
9 files changed
+947
-51
No files matched your search
@@ -20,6 +20,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
.get("/", async ({ query }) => {
|
||||
const lang = (query as any).lang || 'th';
|
||||
const categories = await prisma.category.findMany({
|
||||
where: { deletedAt: null },
|
||||
orderBy: { name: "asc" },
|
||||
include: {
|
||||
translations: true,
|
||||
@@ -45,7 +46,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
|
||||
const [category, total] = await Promise.all([
|
||||
prisma.category.findUnique({
|
||||
where: { id },
|
||||
where: { id, deletedAt: null },
|
||||
include: {
|
||||
translations: true,
|
||||
products: {
|
||||
@@ -118,7 +119,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
if (isNaN(id)) return status(400, { message: "Invalid category ID" });
|
||||
|
||||
try {
|
||||
const categoryExists = await prisma.category.findUnique({ where: { id } });
|
||||
const categoryExists = await prisma.category.findFirst({ where: { id, deletedAt: null } });
|
||||
if (!categoryExists) return status(404, { message: "Category not found" });
|
||||
|
||||
const payload = body as any;
|
||||
@@ -170,7 +171,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
|
||||
try {
|
||||
const category = await prisma.category.update({
|
||||
where: { id },
|
||||
where: { id, deletedAt: null },
|
||||
data: {
|
||||
imageUrl: body.imageUrl,
|
||||
},
|
||||
@@ -217,7 +218,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
|
||||
try {
|
||||
const category = await prisma.category.update({
|
||||
where: { id },
|
||||
where: { id, deletedAt: null },
|
||||
data: {
|
||||
name: body.name,
|
||||
imageUrl: body.imageUrl,
|
||||
@@ -246,7 +247,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
|
||||
try {
|
||||
const category = await prisma.category.findUnique({
|
||||
where: { id },
|
||||
where: { id, deletedAt: null },
|
||||
include: { _count: { select: { products: true } } }
|
||||
});
|
||||
|
||||
@@ -255,8 +256,12 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
return status(400, { message: "Cannot delete category with existing products" });
|
||||
}
|
||||
|
||||
await prisma.category.delete({ where: { id } });
|
||||
return { success: true };
|
||||
const deletedAt = new Date();
|
||||
await prisma.category.update({
|
||||
where: { id },
|
||||
data: { deletedAt },
|
||||
});
|
||||
return { success: true, softDeleted: true, id, deletedAt };
|
||||
} catch (err: any) {
|
||||
return status(500, { message: "Failed to delete category" });
|
||||
}
|
||||
|
||||
@@ -734,7 +734,7 @@ export async function hydrateSectionPayload(section: any, lang: string) {
|
||||
if (Array.isArray(payload.categoryIds) && payload.categoryIds.length > 0) {
|
||||
const ids = payload.categoryIds.map(Number);
|
||||
categories = await prisma.category.findMany({
|
||||
where: { id: { in: ids } },
|
||||
where: { id: { in: ids }, deletedAt: null },
|
||||
include: {
|
||||
translations: true,
|
||||
_count: {
|
||||
@@ -745,6 +745,7 @@ export async function hydrateSectionPayload(section: any, lang: string) {
|
||||
categories.sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
|
||||
} else {
|
||||
categories = await prisma.category.findMany({
|
||||
where: { deletedAt: null },
|
||||
include: {
|
||||
translations: true,
|
||||
_count: {
|
||||
|
||||
@@ -21,6 +21,18 @@ function defaultProductDetailSections(productId: number) {
|
||||
];
|
||||
}
|
||||
|
||||
async function assertActiveCategory(categoryId: number, client: any = prisma) {
|
||||
const category = await client.category.findFirst({
|
||||
where: { id: categoryId, deletedAt: null },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!category) {
|
||||
const error = new Error("Category not found");
|
||||
(error as any).code = "CATEGORY_NOT_FOUND";
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
.decorate("validateVariants", (options: any[] = [], variants: any[] = []) => {
|
||||
if (options.length > 3) throw new Error("Options array length cannot exceed 3.");
|
||||
@@ -522,7 +534,10 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
const updatedProduct = await prisma.$transaction(async (tx) => {
|
||||
// 1. Update basic product info
|
||||
const updateData: any = {};
|
||||
if (categoryId !== undefined) updateData.categoryId = categoryId;
|
||||
if (categoryId !== undefined) {
|
||||
await assertActiveCategory(categoryId, tx);
|
||||
updateData.categoryId = categoryId;
|
||||
}
|
||||
if (body.options !== undefined) updateData.options = body.options;
|
||||
|
||||
const prod = await tx.product.update({
|
||||
@@ -632,6 +647,9 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
|
||||
return { success: true, product: updatedProduct };
|
||||
} catch (err: any) {
|
||||
if (err?.code === "CATEGORY_NOT_FOUND") {
|
||||
return status(400, { success: false, message: "Category not found" });
|
||||
}
|
||||
console.error("Update product error:", err);
|
||||
return status(500, { success: false, message: err?.message || "Failed to update product" });
|
||||
}
|
||||
@@ -690,12 +708,15 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
const product = await prisma.$transaction(async (tx) => {
|
||||
let categoryId = payload.categoryId;
|
||||
if (!categoryId && payload.categoryName) {
|
||||
let cat = await tx.category.findUnique({ where: { name: payload.categoryName } });
|
||||
let cat = await tx.category.findFirst({
|
||||
where: { name: payload.categoryName, deletedAt: null },
|
||||
});
|
||||
if (!cat) {
|
||||
cat = await tx.category.create({ data: { name: payload.categoryName } });
|
||||
}
|
||||
categoryId = cat.id;
|
||||
}
|
||||
if (categoryId) await assertActiveCategory(categoryId, tx);
|
||||
|
||||
let brandId = payload.brandId;
|
||||
if (!brandId && payload.brandName) {
|
||||
@@ -775,6 +796,9 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
|
||||
return { success: true, product };
|
||||
} catch (err: any) {
|
||||
if (err?.code === "CATEGORY_NOT_FOUND") {
|
||||
return status(400, { success: false, message: "Category not found" });
|
||||
}
|
||||
console.error("Create product error:", err);
|
||||
return status(500, { success: false, message: err?.message || "Failed to create product" });
|
||||
}
|
||||
@@ -806,12 +830,15 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
|
||||
let categoryId = payload.categoryId;
|
||||
if (!categoryId && payload.categoryName) {
|
||||
let cat = await tx.category.findUnique({ where: { name: payload.categoryName } });
|
||||
let cat = await tx.category.findFirst({
|
||||
where: { name: payload.categoryName, deletedAt: null },
|
||||
});
|
||||
if (!cat) {
|
||||
cat = await tx.category.create({ data: { name: payload.categoryName } });
|
||||
}
|
||||
categoryId = cat.id;
|
||||
}
|
||||
if (categoryId) await assertActiveCategory(categoryId, tx);
|
||||
|
||||
let brandId = payload.brandId;
|
||||
if (!brandId && payload.brandName) {
|
||||
@@ -892,6 +919,9 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
|
||||
return { success: true, products: createdProducts };
|
||||
} catch (err: any) {
|
||||
if (err?.code === "CATEGORY_NOT_FOUND") {
|
||||
return status(400, { success: false, message: "Category not found" });
|
||||
}
|
||||
console.error("Bulk create products error:", err);
|
||||
return status(500, { success: false, message: err?.message || "Failed to bulk create products" });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user