x
This commit is contained in:
1 parent
c2269ea090
commit
14d3282a81
8 files changed
+226
-39
No files matched your search
@@ -0,0 +1,7 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Product" ADD COLUMN IF NOT EXISTS "isDeleted" BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE "Product" ADD COLUMN IF NOT EXISTS "deletedAt" TIMESTAMP(3);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX IF NOT EXISTS "Product_isDeleted_idx" ON "Product"("isDeleted");
|
||||
CREATE INDEX IF NOT EXISTS "Product_categoryId_isDeleted_idx" ON "Product"("categoryId", "isDeleted");
|
||||
@@ -72,8 +72,13 @@ model Product {
|
||||
reviews Review[]
|
||||
detailSections ProductDetailSection[]
|
||||
translations ProductTranslation[]
|
||||
isDeleted Boolean @default(false)
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([isDeleted])
|
||||
@@index([categoryId, isDeleted])
|
||||
}
|
||||
|
||||
model ProductTranslation {
|
||||
|
||||
@@ -50,6 +50,7 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
include: {
|
||||
translations: true,
|
||||
products: {
|
||||
where: { isDeleted: false },
|
||||
include: {
|
||||
brand: true,
|
||||
category: { include: { translations: true } },
|
||||
@@ -62,11 +63,11 @@ export const categoriesRoute = new Elysia({ prefix: "/categories" })
|
||||
take: limit,
|
||||
},
|
||||
_count: {
|
||||
select: { products: true }
|
||||
select: { products: { where: { isDeleted: false } } }
|
||||
}
|
||||
},
|
||||
}),
|
||||
prisma.product.count({ where: { categoryId: id } }),
|
||||
prisma.product.count({ where: { categoryId: id, isDeleted: false } }),
|
||||
]);
|
||||
|
||||
if (!category) return status(404, { message: "Category not found" });
|
||||
|
||||
@@ -1242,7 +1242,7 @@ async function resolveProductsForSection(payload: any, lang: string) {
|
||||
|
||||
if (payload.type === "featured") {
|
||||
products = await prisma.product.findMany({
|
||||
where: { categoryId: Number(payload.categoryId) || 1 },
|
||||
where: { categoryId: Number(payload.categoryId) || 1, isDeleted: false },
|
||||
include: productInclude,
|
||||
take: limit,
|
||||
});
|
||||
@@ -1251,7 +1251,7 @@ async function resolveProductsForSection(payload: any, lang: string) {
|
||||
(payload.scentId || payload.brandId)
|
||||
) {
|
||||
products = await prisma.product.findMany({
|
||||
where: { brandId: Number(payload.brandId || payload.scentId) },
|
||||
where: { brandId: Number(payload.brandId || payload.scentId), isDeleted: false },
|
||||
include: productInclude,
|
||||
take: limit,
|
||||
});
|
||||
@@ -1259,13 +1259,14 @@ async function resolveProductsForSection(payload: any, lang: string) {
|
||||
const ids = payload.productIds.map(Number);
|
||||
if (ids.length > 0) {
|
||||
products = await prisma.product.findMany({
|
||||
where: { id: { in: ids } },
|
||||
where: { id: { in: ids }, isDeleted: false },
|
||||
include: productInclude,
|
||||
});
|
||||
products.sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
|
||||
}
|
||||
} else {
|
||||
products = await prisma.product.findMany({
|
||||
where: { isDeleted: false },
|
||||
include: productInclude,
|
||||
take: limit,
|
||||
});
|
||||
|
||||
@@ -122,7 +122,10 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
const limit = query.limit ? parseInt(query.limit) : 12;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const includeDeleted = query.includeDeleted === 'true';
|
||||
|
||||
const where = {
|
||||
...(!includeDeleted && { isDeleted: false }),
|
||||
...(categoryId && { categoryId }),
|
||||
...(brandId && { brandId }),
|
||||
...(search && {
|
||||
@@ -255,7 +258,8 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
},
|
||||
});
|
||||
|
||||
if (!product) return status(404, { message: "Product not found" });
|
||||
const includeDeleted = query.includeDeleted === 'true';
|
||||
if (!product || (!includeDeleted && product.isDeleted)) return status(404, { message: "Product not found" });
|
||||
|
||||
if (lang === 'all') {
|
||||
const nameObj: any = {};
|
||||
@@ -1011,4 +1015,73 @@ export const productsRoute = new Elysia({ prefix: "/products" })
|
||||
tags: ["products"],
|
||||
},
|
||||
}
|
||||
)
|
||||
.delete(
|
||||
"/:id",
|
||||
async ({ params, status }) => {
|
||||
const id = parseInt(params.id);
|
||||
if (isNaN(id)) return status(400, { success: false, message: "Invalid product ID" });
|
||||
|
||||
const existing = await prisma.product.findUnique({
|
||||
where: { id },
|
||||
select: { id: true, isDeleted: true },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return status(404, { success: false, message: "Product not found" });
|
||||
}
|
||||
|
||||
await prisma.product.update({
|
||||
where: { id },
|
||||
data: {
|
||||
isDeleted: true,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return { success: true, message: "Product deleted successfully" };
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
summary: "Soft Delete Product",
|
||||
tags: ["products"],
|
||||
},
|
||||
}
|
||||
)
|
||||
.post(
|
||||
"/bulk-delete",
|
||||
async ({ body, status }) => {
|
||||
const { ids } = body as { ids?: number[] };
|
||||
if (!Array.isArray(ids) || ids.length === 0) {
|
||||
return status(400, { success: false, message: "Invalid or empty IDs array" });
|
||||
}
|
||||
|
||||
const validIds = ids.map(id => Number(id)).filter(id => !isNaN(id));
|
||||
if (validIds.length === 0) {
|
||||
return status(400, { success: false, message: "No valid IDs provided" });
|
||||
}
|
||||
|
||||
const result = await prisma.product.updateMany({
|
||||
where: { id: { in: validIds } },
|
||||
data: {
|
||||
isDeleted: true,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
count: result.count,
|
||||
message: `Successfully deleted ${result.count} products`,
|
||||
};
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
ids: t.Array(t.Numeric()),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Bulk Soft Delete Products",
|
||||
tags: ["products"],
|
||||
},
|
||||
}
|
||||
);
|
||||
Reference in new issue
Block a user