294 lines
7.8 KiB
TypeScript
294 lines
7.8 KiB
TypeScript
// Store Helpers - Database operations for cache initialization
|
|
// These are used by stores in apps/backend/src/stores/
|
|
|
|
import { db } from '../db/db_index'
|
|
import {
|
|
homeBanners,
|
|
productInfo,
|
|
units,
|
|
productSlots,
|
|
deliverySlotInfo,
|
|
specialDeals,
|
|
storeInfo,
|
|
productTags,
|
|
productTagInfo,
|
|
userIncidents,
|
|
} from '../db/schema'
|
|
import { eq, and, gt, sql, isNotNull, asc } from 'drizzle-orm'
|
|
|
|
// ============================================================================
|
|
// BANNER STORE HELPERS
|
|
// ============================================================================
|
|
|
|
export interface BannerData {
|
|
id: number
|
|
name: string
|
|
imageUrl: string | null
|
|
serialNum: number | null
|
|
productIds: number[] | null
|
|
createdAt: Date
|
|
}
|
|
|
|
export async function getAllBannersForCache(): Promise<BannerData[]> {
|
|
return db.query.homeBanners.findMany({
|
|
where: isNotNull(homeBanners.serialNum),
|
|
orderBy: asc(homeBanners.serialNum),
|
|
})
|
|
}
|
|
|
|
// ============================================================================
|
|
// PRODUCT STORE HELPERS
|
|
// ============================================================================
|
|
|
|
export interface ProductBasicData {
|
|
id: number
|
|
name: string
|
|
shortDescription: string | null
|
|
longDescription: string | null
|
|
price: string
|
|
marketPrice: string | null
|
|
images: unknown
|
|
isOutOfStock: boolean
|
|
storeId: number | null
|
|
unitShortNotation: string
|
|
incrementStep: number
|
|
productQuantity: number
|
|
isFlashAvailable: boolean
|
|
flashPrice: string | null
|
|
}
|
|
|
|
export interface StoreBasicData {
|
|
id: number
|
|
name: string
|
|
description: string | null
|
|
}
|
|
|
|
export interface DeliverySlotData {
|
|
productId: number
|
|
id: number
|
|
deliveryTime: Date
|
|
freezeTime: Date
|
|
isCapacityFull: boolean
|
|
}
|
|
|
|
export interface SpecialDealData {
|
|
productId: number
|
|
quantity: string
|
|
price: string
|
|
validTill: Date
|
|
}
|
|
|
|
export interface ProductTagData {
|
|
productId: number
|
|
tagName: string
|
|
}
|
|
|
|
export async function getAllProductsForCache(): Promise<ProductBasicData[]> {
|
|
const results = 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))
|
|
|
|
return results.map((product) => ({
|
|
...product,
|
|
price: String(product.price ?? '0'),
|
|
marketPrice: product.marketPrice ? String(product.marketPrice) : null,
|
|
flashPrice: product.flashPrice ? String(product.flashPrice) : null,
|
|
}))
|
|
}
|
|
|
|
export async function getAllStoresForCache(): Promise<StoreBasicData[]> {
|
|
return db.query.storeInfo.findMany({
|
|
columns: { id: true, name: true, description: true },
|
|
})
|
|
}
|
|
|
|
export async function getAllDeliverySlotsForCache(): Promise<DeliverySlotData[]> {
|
|
return db
|
|
.select({
|
|
productId: productSlots.productId,
|
|
id: deliverySlotInfo.id,
|
|
deliveryTime: deliverySlotInfo.deliveryTime,
|
|
freezeTime: deliverySlotInfo.freezeTime,
|
|
isCapacityFull: deliverySlotInfo.isCapacityFull,
|
|
})
|
|
.from(productSlots)
|
|
.innerJoin(deliverySlotInfo, eq(productSlots.slotId, deliverySlotInfo.id))
|
|
.where(
|
|
and(
|
|
eq(deliverySlotInfo.isActive, true),
|
|
eq(deliverySlotInfo.isCapacityFull, false),
|
|
gt(deliverySlotInfo.deliveryTime, sql`CURRENT_TIMESTAMP`)
|
|
)
|
|
)
|
|
}
|
|
|
|
export async function getAllSpecialDealsForCache(): Promise<SpecialDealData[]> {
|
|
const results = await db
|
|
.select({
|
|
productId: specialDeals.productId,
|
|
quantity: specialDeals.quantity,
|
|
price: specialDeals.price,
|
|
validTill: specialDeals.validTill,
|
|
})
|
|
.from(specialDeals)
|
|
.where(gt(specialDeals.validTill, sql`CURRENT_TIMESTAMP`))
|
|
|
|
return results.map((deal) => ({
|
|
...deal,
|
|
quantity: String(deal.quantity ?? '0'),
|
|
price: String(deal.price ?? '0'),
|
|
}))
|
|
}
|
|
|
|
export async function getAllProductTagsForCache(): Promise<ProductTagData[]> {
|
|
return db
|
|
.select({
|
|
productId: productTags.productId,
|
|
tagName: productTagInfo.tagName,
|
|
})
|
|
.from(productTags)
|
|
.innerJoin(productTagInfo, eq(productTags.tagId, productTagInfo.id))
|
|
}
|
|
|
|
// ============================================================================
|
|
// PRODUCT TAG STORE HELPERS
|
|
// ============================================================================
|
|
|
|
export interface TagBasicData {
|
|
id: number
|
|
tagName: string
|
|
tagDescription: string | null
|
|
imageUrl: string | null
|
|
isDashboardTag: boolean
|
|
relatedStores: unknown
|
|
}
|
|
|
|
export interface TagProductMapping {
|
|
tagId: number
|
|
productId: number
|
|
}
|
|
|
|
export async function getAllTagsForCache(): Promise<TagBasicData[]> {
|
|
return db
|
|
.select({
|
|
id: productTagInfo.id,
|
|
tagName: productTagInfo.tagName,
|
|
tagDescription: productTagInfo.tagDescription,
|
|
imageUrl: productTagInfo.imageUrl,
|
|
isDashboardTag: productTagInfo.isDashboardTag,
|
|
relatedStores: productTagInfo.relatedStores,
|
|
})
|
|
.from(productTagInfo)
|
|
}
|
|
|
|
export async function getAllTagProductMappings(): Promise<TagProductMapping[]> {
|
|
return db
|
|
.select({
|
|
tagId: productTags.tagId,
|
|
productId: productTags.productId,
|
|
})
|
|
.from(productTags)
|
|
}
|
|
|
|
// ============================================================================
|
|
// SLOT STORE HELPERS
|
|
// ============================================================================
|
|
|
|
export interface SlotWithProductsData {
|
|
id: number
|
|
deliveryTime: Date
|
|
freezeTime: Date
|
|
isActive: boolean
|
|
isCapacityFull: boolean
|
|
productSlots: Array<{
|
|
product: {
|
|
id: number
|
|
name: string
|
|
productQuantity: number
|
|
shortDescription: string | null
|
|
price: string
|
|
marketPrice: string | null
|
|
unit: { shortNotation: string } | null
|
|
store: { id: number; name: string; description: string | null } | null
|
|
images: unknown
|
|
isOutOfStock: boolean
|
|
storeId: number | null
|
|
}
|
|
}>
|
|
}
|
|
|
|
export async function getAllSlotsWithProductsForCache(): Promise<SlotWithProductsData[]> {
|
|
const now = new Date()
|
|
|
|
return db.query.deliverySlotInfo.findMany({
|
|
where: and(
|
|
eq(deliverySlotInfo.isActive, true),
|
|
gt(deliverySlotInfo.deliveryTime, now)
|
|
),
|
|
with: {
|
|
productSlots: {
|
|
with: {
|
|
product: {
|
|
with: {
|
|
unit: true,
|
|
store: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
orderBy: asc(deliverySlotInfo.deliveryTime),
|
|
}) as Promise<SlotWithProductsData[]>
|
|
}
|
|
|
|
// ============================================================================
|
|
// USER NEGATIVITY STORE HELPERS
|
|
// ============================================================================
|
|
|
|
export interface UserNegativityData {
|
|
userId: number
|
|
totalNegativityScore: number
|
|
}
|
|
|
|
export async function getAllUserNegativityScores(): Promise<UserNegativityData[]> {
|
|
const results = await db
|
|
.select({
|
|
userId: userIncidents.userId,
|
|
totalNegativityScore: sql`sum(${userIncidents.negativityScore})`,
|
|
})
|
|
.from(userIncidents)
|
|
.groupBy(userIncidents.userId)
|
|
|
|
return results.map((result) => ({
|
|
userId: result.userId,
|
|
totalNegativityScore: Number(result.totalNegativityScore ?? 0),
|
|
}))
|
|
}
|
|
|
|
export async function getUserNegativityScore(userId: number): Promise<number> {
|
|
const [result] = await db
|
|
.select({
|
|
totalNegativityScore: sql`sum(${userIncidents.negativityScore})`,
|
|
})
|
|
.from(userIncidents)
|
|
.where(eq(userIncidents.userId, userId))
|
|
.limit(1)
|
|
|
|
return Number(result?.totalNegativityScore ?? 0)
|
|
}
|