freshyo/apps/backend/src/services/user/product-service.ts
2026-03-07 16:24:24 +05:30

138 lines
3.7 KiB
TypeScript

import { db } from '@/src/db/db_index'
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productReviews, users } from '@/src/db/schema'
import { eq, and, gt, sql, desc } from 'drizzle-orm'
/**
* Get product basic info with unit
*/
export async function getProductWithUnit(productId: number) {
return db
.select({
id: productInfo.id,
name: productInfo.name,
shortDescription: productInfo.shortDescription,
longDescription: productInfo.longDescription,
price: productInfo.price,
marketPrice: productInfo.marketPrice,
images: productInfo.images,
isOutOfStock: productInfo.isOutOfStock,
storeId: productInfo.storeId,
unitShortNotation: units.shortNotation,
incrementStep: productInfo.incrementStep,
productQuantity: productInfo.productQuantity,
isFlashAvailable: productInfo.isFlashAvailable,
flashPrice: productInfo.flashPrice,
})
.from(productInfo)
.innerJoin(units, eq(productInfo.unitId, units.id))
.where(eq(productInfo.id, productId))
.limit(1)
}
/**
* Get store info by ID
*/
export async function getStoreById(storeId: number) {
return db.query.storeInfo.findFirst({
where: eq(storeInfo.id, storeId),
columns: { id: true, name: true, description: true },
})
}
/**
* Get delivery slots for product
*/
export async function getProductDeliverySlots(productId: number) {
return db
.select({
id: deliverySlotInfo.id,
deliveryTime: deliverySlotInfo.deliveryTime,
freezeTime: deliverySlotInfo.freezeTime,
})
.from(productSlots)
.innerJoin(deliverySlotInfo, eq(productSlots.slotId, deliverySlotInfo.id))
.where(
and(
eq(productSlots.productId, productId),
eq(deliverySlotInfo.isActive, true),
gt(deliverySlotInfo.deliveryTime, sql`NOW()`),
gt(deliverySlotInfo.freezeTime, sql`NOW()`)
)
)
.orderBy(deliverySlotInfo.deliveryTime)
}
/**
* Get special deals for product
*/
export async function getProductSpecialDeals(productId: number) {
return db
.select({
quantity: specialDeals.quantity,
price: specialDeals.price,
validTill: specialDeals.validTill,
})
.from(specialDeals)
.where(
and(
eq(specialDeals.productId, productId),
gt(specialDeals.validTill, sql`NOW()`)
)
)
.orderBy(specialDeals.quantity)
}
/**
* Get product reviews with user info
*/
export async function getProductReviews(productId: number, limit: number, offset: number) {
return db
.select({
id: productReviews.id,
reviewBody: productReviews.reviewBody,
ratings: productReviews.ratings,
imageUrls: productReviews.imageUrls,
reviewTime: productReviews.reviewTime,
userName: users.name,
})
.from(productReviews)
.innerJoin(users, eq(productReviews.userId, users.id))
.where(eq(productReviews.productId, productId))
.orderBy(desc(productReviews.reviewTime))
.limit(limit)
.offset(offset)
}
/**
* Count reviews for product
*/
export async function countProductReviews(productId: number) {
const result = await db
.select({ count: sql`count(*)` })
.from(productReviews)
.where(eq(productReviews.productId, productId))
return Number(result[0].count)
}
/**
* Check if product exists
*/
export async function checkProductExists(productId: number) {
return db.query.productInfo.findFirst({
where: eq(productInfo.id, productId),
})
}
/**
* Insert new review
*/
export async function insertReview(data: {
userId: number
productId: number
reviewBody: string
ratings: number
imageUrls: string[]
}) {
return db.insert(productReviews).values(data).returning()
}