Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ model Product {
description String @db.VarChar(1000)
scoreValue Int
productInCategories ProductInCategory[]
scores ProductScore[]
hotSellProduct HotSellProduct?
installmentPrice Int?
isBestseller Boolean?
hasFreeShipping Boolean?
scores ProductScore[]
productComment ProductComment?
}

Expand Down Expand Up @@ -132,4 +133,14 @@ model Advertisement {
imageSrc String @db.VarChar(200)
description String @db.VarChar(1000)
url String @db.VarChar(300)
}

model HotSellProduct {
id Int @id @default(autoincrement())
addDate DateTime @default(now())
expiredDate DateTime @default(now())
startDate DateTime @default(now())
maxQuantity Int
product Product @relation(fields: [productId], references: [id])
productId Int @unique
}
34 changes: 18 additions & 16 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import express from 'express';
import cors from 'cors';
import express from "express";
import cors from "cors";
import { productRouter } from "./products";
import { recommendedProductRouter } from './recommendedProducts/routes';
import { navigationRouter } from './navigations/routes';
import { commentRouter } from './comments/routes';
import { newsletterRouter } from './newsletter/routes';
import { advertisementRoute } from './advertising/routes';
import { recommendedProductRouter } from "./recommendedProducts/routes";
import { navigationRouter } from "./navigations/routes";
import { commentRouter } from "./comments/routes";
import { newsletterRouter } from "./newsletter/routes";
import { advertisementRoute } from "./advertising/routes";
import { hotSellProductRouter } from "./hotSellProduct/routes";

const app = express();
const port = process.env.PORT || 4000;
app.use(express.json());
app.use(cors());
app.use('/product/', productRouter);
app.use('/recommendedProduct', recommendedProductRouter)
app.use('/navigation', navigationRouter)
app.use('/comment', commentRouter)
app.use('/newsletter/', newsletterRouter)
app.use('/advertisement', advertisementRoute)
app.use("/product/", productRouter);
app.use("/recommendedProduct", recommendedProductRouter);
app.use("/navigation", navigationRouter);
app.use("/comment", commentRouter);
app.use("/newsletter/", newsletterRouter);
app.use("/advertisement", advertisementRoute);
app.use("/hotSellProduct", hotSellProductRouter);

app.listen(port, () => {
const runningMessage = `Server running at http://localhost:${port}`;
console.log(runningMessage);
})
const runningMessage = `Server running at http://localhost:${port}`;
console.log(runningMessage);
});
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export const CONFIG = {
MAX_BESTSELLS_PRODUCTS: Number(process.env.MAX_BESTSELLS_PRODUCTS),
SCORES_MAX_SIZE: Number(process.env.SCORES_MAX_SIZE),
BASE_PRODUCT_COMMENTS_COUNT: Number(process.env.BASE_PRODUCT_COMMENTS_COUNT),
MAX_SEARCH_RESULT: Number(process.env.MAX_SEARCH_RESULT)
MAX_SEARCH_RESULT: Number(process.env.MAX_SEARCH_RESULT),
DAYS_OF_SEARCH_NEXT_HOTSELL: Number(process.env.DAYS_OF_SEARCH_NEXT_HOTSELL)
}
92 changes: 92 additions & 0 deletions src/hotSellProduct/hotSellProduct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { getOrderProductByDateRange } from "../orderProducts/orderProducts";
import { prisma } from "../../prisma/prisma";
import { CONFIG } from "../config";

const getProductSoldQuantity = async (
dateFrom: Date,
dateTo: Date,
productId: number
) => {
const ordersProduct = await getOrderProductByDateRange(
dateFrom,
dateTo,
productId
);

if (ordersProduct.length === 0) return 0;

const quantityArray = ordersProduct.map(
(ordersProduct) => ordersProduct.quantity
);

const sumQuantity = quantityArray.reduce(
(accumulator, currentValue) => accumulator + currentValue
);

return sumQuantity;
};

export const getHotSellProduct = async () => {
const yesterdayBeginOfDay = new Date();
yesterdayBeginOfDay.setDate(new Date().getDate() - 1);
yesterdayBeginOfDay.setHours(1, 0, 0, 0);

const dateLimitUntilNextHotSale = new Date();
dateLimitUntilNextHotSale.setDate(
dateLimitUntilNextHotSale.getDate() + CONFIG.DAYS_OF_SEARCH_NEXT_HOTSELL
);

const hotSellProduct = await prisma.hotSellProduct.findFirst({
where: {
maxQuantity: {
gt: 0,
},
startDate: {
gte: yesterdayBeginOfDay,
},
expiredDate: {
gte: new Date(),
},
},
include: {
product: true,
},
});

const nextHotSellProduct = await prisma.hotSellProduct.findFirst({
where: {
maxQuantity: {
gt: 0,
},
startDate: {
gte: new Date(),
lte: dateLimitUntilNextHotSale,
},
},
select: {
startDate: true,
},
});

if (!hotSellProduct || hotSellProduct.product.quantity < 1) {
return null;
}

const orderQuantity = await getProductSoldQuantity(
hotSellProduct.addDate,
hotSellProduct.expiredDate,
hotSellProduct.productId
);

return {
id: hotSellProduct.productId,
name: hotSellProduct.product.name,
imageSrc: hotSellProduct.product.imageSrc,
price: hotSellProduct.product.price,
priceDiscount: hotSellProduct.product.discountPrice,
endDateTime: hotSellProduct.expiredDate,
orderQuantity,
maxQuantity: hotSellProduct.maxQuantity,
nextHotSellProductDate: nextHotSellProduct?.startDate,
};
};
30 changes: 30 additions & 0 deletions src/hotSellProduct/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import express, { Request, Response } from "express";
import { getHotSellProduct } from "./hotSellProduct";
import { getCacheData, setCacheData } from "../cache";

function createHotSellProductRouter() {
return express.Router().get("", async (_, resp: Response) => {
let dataResult = await getCacheData("hotsellProduct");
if (dataResult) {
dataResult = JSON.parse(dataResult);
} else {
dataResult = await getHotSellProduct();
if (dataResult) {
await setCacheData(
"hotsellProduct",
JSON.stringify(dataResult)
);
}
}

if (!dataResult) {
return resp.status(404).send({
error: `No hotSell product found`,
});
}

return resp.status(200).send(dataResult);
});
}

export const hotSellProductRouter = createHotSellProductRouter();
38 changes: 28 additions & 10 deletions src/orderProducts/orderProducts.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import { prisma } from "../../prisma/prisma";

export const getOrderProductsByDate = async (date: Date) => {
const orderProducts = await prisma.orderProduct.findMany({
where: {
addDate: {
gt: date
}
}
});

return orderProducts;
}
const orderProducts = await prisma.orderProduct.findMany({
where: {
addDate: {
gt: date,
},
},
});

return orderProducts;
};

export const getOrderProductByDateRange = async (
dateFrom: Date,
dateTo: Date,
productId: number
) => {
const orderProducts = await prisma.orderProduct.findMany({
where: {
addDate: {
gte: dateFrom,
lte: dateTo,
},
productId: productId,
},
});

return orderProducts;
};