freshyo/apps/backend/src/stores/product-store.ts
2026-07-31 18:19:07 +05:30

264 lines
9.1 KiB
TypeScript

// import redisClient from '@/src/lib/redis-client'
import {
getAllProductsForCache,
getAllStoresForCache,
getAllDeliverySlotsForCache,
getAllSpecialDealsForCache,
getAllProductTagsForCache,
getProductById as getProductByIdFromDb,
type ProductBasicData,
type StoreBasicData,
type DeliverySlotData,
type SpecialDealData,
type ProductTagData,
} from '@/src/dbService'
import { scaffoldAssetUrl } from '@/src/lib/s3-client'
// Uniform Product Type (matches getProductDetails return)
interface Product {
id: number
name: string
shortDescription: string | null
longDescription: string | null
price: string
marketPrice: string | null
unitNotation: string
images: string[]
isOutOfStock: boolean
store: { id: number; name: string; description: string | null } | null
incrementStep: number
productQuantity: number
isFlashAvailable: boolean
flashPrice: string | null
deliverySlots: Array<{ id: number; deliveryTime: Date; freezeTime: Date; isCapacityFull: boolean }>
specialDeals: Array<{ quantity: string; price: string; validTill: Date }>
productTags: string[]
}
export async function initializeProducts(): Promise<void> {
try {
console.log('Initializing product store in Redis...')
// Fetch all products with full details (similar to productMega logic)
const productsData = await getAllProductsForCache()
/*
// Old implementation - direct DB queries:
import { db } from '@/src/db/db_index'
import { productInfo, units } from '@/src/db/schema'
const productsData = await 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));
*/
// Fetch all stores
const allStores = await getAllStoresForCache()
const storeMap = new Map(allStores.map((s) => [s.id, s]))
// Fetch all delivery slots (excluding full capacity slots)
const allDeliverySlots = await getAllDeliverySlotsForCache()
const deliverySlotsMap = new Map<number, DeliverySlotData[]>()
for (const slot of allDeliverySlots) {
if (!deliverySlotsMap.has(slot.skuId))
deliverySlotsMap.set(slot.skuId, [])
deliverySlotsMap.get(slot.skuId)!.push(slot)
}
// Fetch all special deals
const allSpecialDeals = await getAllSpecialDealsForCache()
const specialDealsMap = new Map<number, SpecialDealData[]>()
for (const deal of allSpecialDeals) {
if (!specialDealsMap.has(deal.skuId))
specialDealsMap.set(deal.skuId, [])
specialDealsMap.get(deal.skuId)!.push(deal)
}
// Fetch all product tags
const allProductTags = await getAllProductTagsForCache()
const productTagsMap = new Map<number, string[]>()
for (const tag of allProductTags) {
if (!productTagsMap.has(tag.productId))
productTagsMap.set(tag.productId, [])
productTagsMap.get(tag.productId)!.push(tag.tagName)
}
// Store each product in Redis
// for (const product of productsData) {
// const signedImages = scaffoldAssetUrl(
// (product.images as string[]) || []
// )
// const store = product.storeId
// ? storeMap.get(product.storeId) || null
// : null
// const deliverySlots = deliverySlotsMap.get(product.id) || []
// const specialDeals = specialDealsMap.get(product.id) || []
// const productTags = productTagsMap.get(product.id) || []
//
// const productObj: Product = {
// id: product.id,
// name: product.name,
// shortDescription: product.shortDescription,
// longDescription: product.longDescription,
// price: product.price.toString(),
// marketPrice: product.marketPrice?.toString() || null,
// unitNotation: product.unitShortNotation,
// images: signedImages,
// isOutOfStock: product.isOutOfStock,
// store: store
// ? { id: store.id, name: store.name, description: store.description }
// : null,
// incrementStep: product.incrementStep,
// productQuantity: product.productQuantity,
// isFlashAvailable: product.isFlashAvailable,
// flashPrice: product.flashPrice?.toString() || null,
// deliverySlots: deliverySlots.map((s) => ({
// id: s.id,
// deliveryTime: s.deliveryTime,
// freezeTime: s.freezeTime,
// isCapacityFull: s.isCapacityFull,
// })),
// specialDeals: specialDeals.map((d) => ({
// quantity: d.quantity.toString(),
// price: d.price.toString(),
// validTill: d.validTill,
// })),
// productTags: productTags,
// }
//
// await redisClient.set(`product:${product.id}`, JSON.stringify(productObj))
// }
console.log('Product store initialized successfully')
} catch (error) {
console.error('Error initializing product store:', error)
}
}
export async function getProductById(id: number): Promise<Product | null> {
try {
const allProducts = await getAllProducts()
const product = allProducts.find(p => p.id === id)
return product || null
} catch (error) {
console.error('Error getting product by ID:', error)
return null
}
}
export async function getAllProducts(): Promise<Product[]> {
try {
// Get all keys matching the pattern "product:*"
// const keys = await redisClient.KEYS('product:*')
//
// if (keys.length === 0) {
// return []
// }
//
// // Get all products using MGET for better performance
// const productsData = await redisClient.MGET(keys)
//
// const products: Product[] = []
// for (const productData of productsData) {
// if (productData) {
// products.push(JSON.parse(productData) as Product)
// }
// }
//
// return products
const productsData = await getAllProductsForCache()
const allStores = await getAllStoresForCache()
const storeMap = new Map(allStores.map((s) => [s.id, s]))
const allDeliverySlots = await getAllDeliverySlotsForCache()
const deliverySlotsMap = new Map<number, DeliverySlotData[]>()
for (const slot of allDeliverySlots) {
if (!deliverySlotsMap.has(slot.skuId))
deliverySlotsMap.set(slot.skuId, [])
deliverySlotsMap.get(slot.skuId)!.push(slot)
}
const allSpecialDeals = await getAllSpecialDealsForCache()
const specialDealsMap = new Map<number, SpecialDealData[]>()
for (const deal of allSpecialDeals) {
if (!specialDealsMap.has(deal.skuId))
specialDealsMap.set(deal.skuId, [])
specialDealsMap.get(deal.skuId)!.push(deal)
}
const allProductTags = await getAllProductTagsForCache()
const productTagsMap = new Map<number, string[]>()
for (const tag of allProductTags) {
if (!productTagsMap.has(tag.productId))
productTagsMap.set(tag.productId, [])
productTagsMap.get(tag.productId)!.push(tag.tagName)
}
const products: Product[] = []
for (const product of productsData) {
const signedImages = scaffoldAssetUrl(
(product.images as string[]) || []
)
const store = product.storeId
? storeMap.get(product.storeId) || null
: null
const deliverySlots = deliverySlotsMap.get(product.id) || []
const specialDeals = specialDealsMap.get(product.id) || []
const productTags = productTagsMap.get(product.productId) || []
products.push({
id: product.id,
name: product.name,
shortDescription: product.shortDescription,
longDescription: product.longDescription,
price: product.price.toString(),
marketPrice: product.marketPrice?.toString() || null,
unitNotation: product.unitNotation,
images: signedImages,
isOutOfStock: product.isOutOfStock,
store: store
? { id: store.id, name: store.name, description: store.description }
: null,
incrementStep: product.incrementStep,
productQuantity: product.productQuantity,
isFlashAvailable: product.isFlashAvailable,
flashPrice: product.flashPrice?.toString() || null,
deliverySlots: deliverySlots.map((s) => ({
id: s.id,
deliveryTime: s.deliveryTime,
freezeTime: s.freezeTime,
isCapacityFull: s.isCapacityFull,
})),
specialDeals: specialDeals.map((d) => ({
quantity: d.quantity.toString(),
price: d.price.toString(),
validTill: d.validTill,
})),
productTags: productTags,
})
}
return products
} catch (error) {
console.error('Error getting all products:', error)
return []
}
}