This commit is contained in:
shafi54 2026-05-11 19:25:44 +05:30
parent 4d660e945b
commit 5bacc25627
22 changed files with 57406 additions and 876 deletions

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,7 @@ export const createApp = () => {
// CORS middleware // CORS middleware
app.use(cors({ app.use(cors({
origin: ['http://localhost:5174', 'http://localhost:4174', 'https://ui.freshyo.in'], origin: ['http://localhost:5174', 'http://localhost:4174', 'https://ui.freshyo.in', 'https://webui.freshyo.in', 'https://app.freshyo.in'],
allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
allowHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'Caller-Interface'], allowHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'Caller-Interface'],
credentials: true, credentials: true,

View file

@ -105,6 +105,7 @@ export {
updateSlotCapacity, updateSlotCapacity,
getSlotDeliverySequence, getSlotDeliverySequence,
updateSlotDeliverySequence, updateSlotDeliverySequence,
staleSlotsCleanup,
// Admin - Staff User // Admin - Staff User
getStaffUserByName, getStaffUserByName,
getStaffUserById, getStaffUserById,

View file

@ -19,6 +19,7 @@ import {
updateSlotDeliverySequence as updateSlotDeliverySequenceInDb, updateSlotDeliverySequence as updateSlotDeliverySequenceInDb,
updateSlotProducts as updateSlotProductsInDb, updateSlotProducts as updateSlotProductsInDb,
getSlotsProductIds as getSlotsProductIdsInDb, getSlotsProductIds as getSlotsProductIdsInDb,
staleSlotsCleanup,
} from '@/src/dbService' } from '@/src/dbService'
import type { import type {
AdminDeliverySequenceResult, AdminDeliverySequenceResult,
@ -93,7 +94,7 @@ export const slotsRouter = router({
throw new TRPCError({ code: "UNAUTHORIZED", message: "Access denied" }); throw new TRPCError({ code: "UNAUTHORIZED", message: "Access denied" });
} }
const slots = await getActiveSlotsWithProductsInDb() const slots = await getActiveSlotsWithProductsInDb(20)
/* /*
// Old implementation - direct DB queries: // Old implementation - direct DB queries:
@ -362,6 +363,11 @@ export const slotsRouter = router({
// Reinitialize stores to reflect changes (outside transaction) // Reinitialize stores to reflect changes (outside transaction)
await scheduleStoreInitialization() await scheduleStoreInitialization()
// Fire and forget: cleanup stale product slot associations
staleSlotsCleanup().catch((error) => {
console.error('Failed to cleanup stale slots:', error)
})
return result return result
}), }),

View file

@ -44,7 +44,7 @@ interface RegisterRequest {
const generateToken = async (userId: number): Promise<string> => { const generateToken = async (userId: number): Promise<string> => {
return await new SignJWT({ userId }) return await new SignJWT({ userId })
.setProtectedHeader({ alg: 'HS256' }) .setProtectedHeader({ alg: 'HS256' })
.setExpirationTime('7d') .setExpirationTime('90d')
.sign(getEncodedJwtSecret()); .sign(getEncodedJwtSecret());
}; };

View file

@ -213,7 +213,7 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
const product = productsById[item.productId]; const product = productsById[item.productId];
const quantity = quantities[item.id] || item.quantity; const quantity = quantities[item.id] || item.quantity;
const price = isFlashDelivery ? (product?.flashPrice ?? product?.price ?? 0) : (product?.price || 0); const price = isFlashDelivery ? (product?.flashPrice ?? product?.price ?? 0) : (product?.price || 0);
return sum + price * quantity; return sum + Number(price) * quantity;
}, 0); }, 0);
const dropdownData = useMemo( const dropdownData = useMemo(
() => () =>
@ -442,7 +442,7 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
// } // }
const quantity = quantities[item.id] || item.quantity; const quantity = quantities[item.id] || item.quantity;
const price = isFlashDelivery ? (product?.flashPrice ?? product?.price ?? 0) : (product?.price || 0); const price = isFlashDelivery ? (product?.flashPrice ?? product?.price ?? 0) : (product?.price || 0);
const itemPrice = price * quantity; const itemPrice = (Number(price)) * quantity;
return ( return (
<View key={item.id}> <View key={item.id}>

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,11 @@
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "vite build", "build": "vite build",
"preview": "vite preview --port 4174", "preview": "npm run build && wrangler dev",
"test": "vitest run", "test": "vitest run",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit",
"deploy": "npm run build && wrangler deploy",
"cf-typegen": "wrangler types"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
@ -39,6 +41,7 @@
"zustand": "^5.0.13" "zustand": "^5.0.13"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/vite-plugin": "^1.36.3",
"@tanstack/devtools-vite": "^0.6.0", "@tanstack/devtools-vite": "^0.6.0",
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^19.0.0", "@types/react": "^19.0.0",
@ -46,6 +49,7 @@
"@vitejs/plugin-react": "^6.0.1", "@vitejs/plugin-react": "^6.0.1",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"vite": "^8.0.0", "vite": "^8.0.0",
"vitest": "^4.1.5" "vitest": "^4.1.5",
"wrangler": "^4.90.0"
} }
} }

View file

@ -2,7 +2,8 @@ import { createTRPCReact } from '@trpc/react-query'
import { createTRPCClient, httpBatchLink } from '@trpc/client' import { createTRPCClient, httpBatchLink } from '@trpc/client'
import type { AppRouter } from '@backend/trpc/router' import type { AppRouter } from '@backend/trpc/router'
const BASE_API_URL = 'http://192.168.100.111:8787' // const BASE_API_URL = 'http://192.168.100.111:8787'
export const BASE_API_URL = 'https://worker.freshyo.in'
export const trpc = createTRPCReact<AppRouter>() export const trpc = createTRPCReact<AppRouter>()

View file

@ -5,16 +5,22 @@ import viteReact from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite' import tailwindcss from '@tailwindcss/vite'
import { nitro } from 'nitro/vite' import { nitro } from 'nitro/vite'
import { cloudflare } from "@cloudflare/vite-plugin";
const config = defineConfig({ const config = defineConfig({
resolve: { tsconfigPaths: true }, resolve: { tsconfigPaths: true },
server: { port: 4174 }, server: { port: 4174 },
plugins: [ plugins: [
devtools(), devtools(),
nitro({ rollupConfig: { external: [/^@sentry\//] } }),
tailwindcss(), tailwindcss(),
tanstackStart(), tanstackStart(),
viteReact(), viteReact(),
cloudflare({
viteEnvironment: {
name: "ssr"
}
}),
], ],
}) })
export default config export default config

View file

@ -0,0 +1,12 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "web-ui",
"compatibility_date": "2026-05-10",
"observability": {
"enabled": true
},
"main": "@tanstack/react-start/server-entry",
"compatibility_flags": [
"nodejs_compat"
]
}

View file

@ -118,6 +118,7 @@ export {
updateSlotCapacity, updateSlotCapacity,
getSlotDeliverySequence, getSlotDeliverySequence,
updateSlotDeliverySequence, updateSlotDeliverySequence,
staleSlotsCleanup,
} from './src/admin-apis/slots'; } from './src/admin-apis/slots';
export { export {

View file

@ -6,7 +6,7 @@ import {
vendorSnippets, vendorSnippets,
productGroupInfo, productGroupInfo,
} from '../db/schema' } from '../db/schema'
import { and, asc, desc, eq, gt, inArray } from 'drizzle-orm' import { and, asc, desc, eq, gt, inArray, lt } from 'drizzle-orm'
import type { import type {
AdminDeliverySlot, AdminDeliverySlot,
AdminSlotWithProducts, AdminSlotWithProducts,
@ -61,11 +61,12 @@ const mapVendorSnippet = (snippet: typeof vendorSnippets.$inferSelect): AdminVen
createdAt: snippet.createdAt, createdAt: snippet.createdAt,
}) })
export async function getActiveSlotsWithProducts(): Promise<AdminSlotWithProducts[]> { export async function getActiveSlotsWithProducts(limit: number = 20): Promise<AdminSlotWithProducts[]> {
const slots = await db.query.deliverySlotInfo const slots = await db.query.deliverySlotInfo
.findMany({ .findMany({
where: eq(deliverySlotInfo.isActive, true), where: eq(deliverySlotInfo.isActive, true),
orderBy: desc(deliverySlotInfo.deliveryTime), orderBy: desc(deliverySlotInfo.deliveryTime),
limit,
with: { with: {
productSlots: { productSlots: {
with: { with: {
@ -88,6 +89,27 @@ export async function getActiveSlotsWithProducts(): Promise<AdminSlotWithProduct
})) }))
} }
export async function staleSlotsCleanup(): Promise<number> {
// Get the 20 most recent slot IDs
const recentSlots = await db
.select({ id: deliverySlotInfo.id })
.from(deliverySlotInfo)
.orderBy(desc(deliverySlotInfo.id))
.limit(20)
if (recentSlots.length < 20) {
return 0 // Less than 20 slots exist, nothing to clean
}
// Get the threshold (the 20th most recent slot ID - minimum of the 20)
const threshold = Math.min(...recentSlots.map((s) => s.id))
// Delete product_slots for all slots older than threshold
const result = await db.delete(productSlots).where(lt(productSlots.slotId, threshold))
return result.rowCount || 0
}
export async function getActiveSlots(): Promise<AdminDeliverySlot[]> { export async function getActiveSlots(): Promise<AdminDeliverySlot[]> {
const slots = await db.query.deliverySlotInfo.findMany({ const slots = await db.query.deliverySlotInfo.findMany({
where: eq(deliverySlotInfo.isActive, true), where: eq(deliverySlotInfo.isActive, true),

View file

@ -1,6 +1,6 @@
import { db } from '../db/db_index' import { db } from '../db/db_index'
import { deliverySlotInfo, productInfo, productReviews, productSlots, productTags, specialDeals, storeInfo, units, users } from '../db/schema' import { productInfo, productReviews, specialDeals, storeInfo, units, users } from '../db/schema'
import { and, desc, eq, gt, inArray, sql } from 'drizzle-orm' import { and, desc, eq, gt, sql } from 'drizzle-orm'
import type { UserProductDetailData, UserProductReview } from '@packages/shared' import type { UserProductDetailData, UserProductReview } from '@packages/shared'
const getStringArray = (value: unknown): string[] | null => { const getStringArray = (value: unknown): string[] | null => {
@ -42,25 +42,8 @@ export async function getProductDetailById(productId: number): Promise<UserProdu
columns: { id: true, name: true, description: true }, columns: { id: true, name: true, description: true },
}) : null }) : null
const deliverySlotsData = await db // Note: deliverySlots are now fetched from cache in the frontend via useSlots()
.select({ // This avoids expensive database joins on every product detail view
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),
eq(deliverySlotInfo.isCapacityFull, false),
gt(deliverySlotInfo.deliveryTime, sql`NOW()`),
gt(deliverySlotInfo.freezeTime, sql`NOW()`)
)
)
.orderBy(deliverySlotInfo.deliveryTime)
const specialDealsData = await db const specialDealsData = await db
.select({ .select({
quantity: specialDeals.quantity, quantity: specialDeals.quantity,
@ -95,7 +78,7 @@ export async function getProductDetailById(productId: number): Promise<UserProdu
productQuantity: product.productQuantity, productQuantity: product.productQuantity,
isFlashAvailable: product.isFlashAvailable, isFlashAvailable: product.isFlashAvailable,
flashPrice: product.flashPrice?.toString() || null, flashPrice: product.flashPrice?.toString() || null,
deliverySlots: deliverySlotsData, deliverySlots: [], // Fetched from cache in frontend via useSlots()
specialDeals: specialDealsData.map((deal) => ({ specialDeals: specialDealsData.map((deal) => ({
quantity: deal.quantity.toString(), quantity: deal.quantity.toString(),
price: deal.price.toString(), price: deal.price.toString(),

View file

@ -117,6 +117,7 @@ export {
updateSlotCapacity, updateSlotCapacity,
getSlotDeliverySequence, getSlotDeliverySequence,
updateSlotDeliverySequence, updateSlotDeliverySequence,
staleSlotsCleanup,
} from './src/admin-apis/slots' } from './src/admin-apis/slots'
export { export {

View file

@ -449,7 +449,7 @@ export async function getAllOrders(input: GetAllOrdersInput): Promise<AdminGetAl
flashDeliveryFilter, flashDeliveryFilter,
} = input } = input
let whereCondition: SQL<unknown> | undefined = eq(orders.id, orders.id) let whereCondition: SQL<unknown> | undefined = undefined
if (cursor) { if (cursor) {
whereCondition = and(whereCondition, lt(orders.id, cursor)) whereCondition = and(whereCondition, lt(orders.id, cursor))
} }

View file

@ -6,7 +6,7 @@ import {
vendorSnippets, vendorSnippets,
productGroupInfo, productGroupInfo,
} from '../db/schema' } from '../db/schema'
import { and, asc, desc, eq, gt, inArray } from 'drizzle-orm' import { and, asc, desc, eq, gt, inArray, lt } from 'drizzle-orm'
import type { import type {
AdminDeliverySlot, AdminDeliverySlot,
AdminSlotWithProducts, AdminSlotWithProducts,
@ -97,11 +97,12 @@ const mapVendorSnippet = (snippet: typeof vendorSnippets.$inferSelect): AdminVen
createdAt: coerceDate(snippet.createdAt) ?? new Date(0), createdAt: coerceDate(snippet.createdAt) ?? new Date(0),
}) })
export async function getActiveSlotsWithProducts(): Promise<AdminSlotWithProducts[]> { export async function getActiveSlotsWithProducts(limit: number = 20): Promise<AdminSlotWithProducts[]> {
const slots = await db.query.deliverySlotInfo const slots = await db.query.deliverySlotInfo
.findMany({ .findMany({
where: eq(deliverySlotInfo.isActive, true), where: eq(deliverySlotInfo.isActive, true),
orderBy: desc(deliverySlotInfo.deliveryTime), orderBy: desc(deliverySlotInfo.deliveryTime),
limit,
with: { with: {
productSlots: { productSlots: {
with: { with: {
@ -124,6 +125,27 @@ export async function getActiveSlotsWithProducts(): Promise<AdminSlotWithProduct
})) }))
} }
export async function staleSlotsCleanup(): Promise<number> {
// Get the 20 most recent slot IDs
const recentSlots = await db
.select({ id: deliverySlotInfo.id })
.from(deliverySlotInfo)
.orderBy(desc(deliverySlotInfo.id))
.limit(20)
if (recentSlots.length < 20) {
return 0 // Less than 20 slots exist, nothing to clean
}
// Get the threshold (the 20th most recent slot ID - minimum of the 20)
const threshold = Math.min(...recentSlots.map((s) => s.id))
// Delete product_slots for all slots older than threshold
const result = await db.delete(productSlots).where(lt(productSlots.slotId, threshold))
return result.changes || 0
}
export async function getActiveSlots(): Promise<AdminDeliverySlot[]> { export async function getActiveSlots(): Promise<AdminDeliverySlot[]> {
const slots = await db.query.deliverySlotInfo.findMany({ const slots = await db.query.deliverySlotInfo.findMany({
where: eq(deliverySlotInfo.isActive, true), where: eq(deliverySlotInfo.isActive, true),

View file

@ -42,25 +42,8 @@ export async function getProductDetailById(productId: number): Promise<UserProdu
columns: { id: true, name: true, description: true }, columns: { id: true, name: true, description: true },
}) : null }) : null
const deliverySlotsData = await db // Note: deliverySlots are now fetched from cache in the frontend via useSlots()
.select({ // This avoids expensive database joins on every product detail view
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),
eq(deliverySlotInfo.isCapacityFull, false),
gt(deliverySlotInfo.deliveryTime, sql`CURRENT_TIMESTAMP`),
gt(deliverySlotInfo.freezeTime, sql`CURRENT_TIMESTAMP`)
)
)
.orderBy(deliverySlotInfo.deliveryTime)
const specialDealsData = await db const specialDealsData = await db
.select({ .select({
quantity: specialDeals.quantity, quantity: specialDeals.quantity,
@ -95,7 +78,7 @@ export async function getProductDetailById(productId: number): Promise<UserProdu
productQuantity: product.productQuantity, productQuantity: product.productQuantity,
isFlashAvailable: product.isFlashAvailable, isFlashAvailable: product.isFlashAvailable,
flashPrice: product.flashPrice?.toString() || null, flashPrice: product.flashPrice?.toString() || null,
deliverySlots: deliverySlotsData, deliverySlots: [], // Fetched from cache in frontend via useSlots()
specialDeals: specialDealsData.map((deal) => ({ specialDeals: specialDealsData.map((deal) => ({
quantity: String(deal.quantity ?? '0'), quantity: String(deal.quantity ?? '0'),
price: String(deal.price ?? '0'), price: String(deal.price ?? '0'),

View file

@ -67,7 +67,7 @@ const isDevMode = Constants.executionEnvironment !== "standalone";
// const BASE_API_URL = 'http://192.168.1.5:8787'; // const BASE_API_URL = 'http://192.168.1.5:8787';
// const BASE_API_URL = 'http://192.168.100.109:8787'; // const BASE_API_URL = 'http://192.168.100.109:8787';
// let BASE_API_URL = "https://raw.freshyo.in"; // let BASE_API_URL = "https://raw.freshyo.in";
// let BASE_API_URL = "https://worker.freshyo.in"; // let BASE_API_URL = "https://worker.freshyo.in";
// let BASE_API_URL = "https://freshyo.technocracy.ovh"; // let BASE_API_URL = "https://freshyo.technocracy.ovh";
let BASE_API_URL = 'http://192.168.100.111:8787'; let BASE_API_URL = 'http://192.168.100.111:8787';
// let BASE_API_URL = 'http://192.168.29.176:4000'; // let BASE_API_URL = 'http://192.168.29.176:4000';

26844
slots.json Normal file

File diff suppressed because it is too large Load diff

145
top_queries.md Normal file
View file

@ -0,0 +1,145 @@
# Top Full-Scan Queries
## 1. Orders with all relations (no filters)
Source: `packages/db_helper_sqlite/src/admin-apis/order.ts:441-499``getAllOrders()`
```sql
select
"id",
"user_id",
"address_id",
"slot_id",
"is_cod",
"is_online_payment",
"payment_info_id",
"total_amount",
"delivery_charge",
"readable_id",
"admin_notes",
"user_notes",
"order_group_id",
"order_group_proportion",
"is_flash_delivery",
"created_at",
(select json_array("id","name","email","mobile","created_at") from (select * from "users" where "users"."id" = "orders"."user_id" limit 1)) as "user",
(select json_array("id","user_id","name","phone","address_line1","address_line2","city","state","pincode","is_default","latitude","longitude","google_maps_url","admin_latitude","admin_longitude","zone_id","created_at") from (select * from "addresses" where "addresses"."id" = "orders"."address_id" limit 1)) as "address",
(select json_array("id","delivery_time","freeze_time","is_active","is_flash","is_capacity_full","delivery_sequence","group_ids") from (select * from "delivery_slot_info" where "delivery_slot_info"."id" = "orders"."slot_id" limit 1)) as "slot",
(select coalesce(json_group_array(json_array("id","order_id","product_id","quantity","price","discounted_price","is_packaged","is_package_verified",(select json_array("id","name","short_description","long_description","unit_id","price","market_price","images","is_out_of_stock","is_suspended","is_flash_available","flash_price","created_at","increment_step","product_quantity","store_id",(select json_array("id","short_notation","full_name") from (select * from "units" where "units"."id" = "orders_orderItems_product"."unit_id" limit 1))) from (select * from "product_info" where "product_info"."id" = "orders_orderItems"."product_id" limit 1)))),json_array()) from "order_items" where "order_items"."order_id" = "orders"."id") as "orderItems",
(select coalesce(json_group_array(json_array("id","order_time","user_id","order_id","is_packaged","is_delivered","is_cancelled","cancel_reason","is_cancelled_by_admin","payment_state","cancellation_user_notes","cancellation_admin_notes","cancellation_reviewed","cancellation_reviewed_at","refund_coupon_id")),json_array()) from "order_status" where "order_status"."order_id" = "orders"."id") as "orderStatus"
from "orders"
where "orders"."id" = "orders"."id"
order by "orders"."created_at" desc
limit ?
```
**Why it's bad**: `where "orders"."id" = "orders"."id"` is an always-true condition — it's a no-op placeholder. When no cursor/slot/filters are provided, this scans ALL orders with 6 levels of nested correlated subqueries, then filters out COD/pending payments in-memory after fetching everything.
---
## 2. Active slots (no date filter)
Source: `packages/db_helper_sqlite/src/admin-apis/slots.ts:32-47``getActiveSlotsWithProducts()`
```sql
select
"id",
"delivery_time",
"freeze_time",
"is_active",
"is_flash",
"is_capacity_full",
"delivery_sequence",
"group_ids",
(select coalesce(json_group_array(json_array("product_id","slot_id",(select json_array("id","name","images") from (select * from "product_info" where "product_info"."id" = "deliverySlotInfo_productSlots"."product_id" limit 1)))),json_array()) from "product_slots" where "product_slots"."slot_id" = "deliverySlotInfo"."id") as "productSlots"
from "delivery_slot_info"
where "deliverySlotInfo"."is_active" = ?
order by "deliverySlotInfo"."delivery_time" desc
```
**Why it's bad**: Only filters `is_active = true`, no `deliveryTime > now` check. Returns past expired slots. Correlated subquery per slot for products.
---
## 3. All slots with products for cache (deep JOINs on every slot)
Source: `packages/db_helper_sqlite/src/stores/store-helpers.ts:236-258``getAllSlotsWithProductsForCache()`
```sql
select
"id",
"delivery_time",
"freeze_time",
"is_active",
"is_flash",
"is_capacity_full",
"delivery_sequence",
"group_ids",
(select coalesce(json_group_array(json_array("product_id","slot_id",(select json_array("id","name","short_description","long_description","unit_id","price","market_price","images","is_out_of_stock","is_suspended","is_flash_available","flash_price","created_at","increment_step","product_quantity","store_id",(select json_array("id","short_notation","full_name") from (select * from "units" where "units"."id" = "deliverySlotInfo_productSlots_product"."unit_id" limit 1)),(select json_array("id","name","description","image_url","created_at","owner") from (select * from "store_info" where "store_info"."id" = "deliverySlotInfo_productSlots_product"."store_id" limit 1))) from (select * from "product_info" where "product_info"."id" = "deliverySlotInfo_productSlots"."product_id" limit 1)))),json_array()) from "product_slots" where "product_slots"."slot_id" = "deliverySlotInfo"."id") as "productSlots"
from "delivery_slot_info"
where ("deliverySlotInfo"."is_active" = ? and "deliverySlotInfo"."delivery_time" > ?)
order by "deliverySlotInfo"."delivery_time" asc
```
**Why it's bad**: Called on every slot lookup (`getSlotById`, `getProductSlots`, `getAllProductsSlots`, `getMultipleProductsSlots`) in `slot-store.ts`. Despite filtering for future active slots, it loads ALL of them with deep nested subqueries (product → unit + store) per product per slot, even when only one slot's data is needed.
---
## 4. Vendor orders (no WHERE at all)
Source: `packages/db_helper_sqlite/src/admin-apis/vendor-snippets.ts:171-187``getVendorOrders()`
```sql
select ... from "orders"
left join "users" ...
left join "order_items" ...
left join "product_info" ...
left join "units" ...
order by "orders"."created_at" desc
```
**Why it's bad**: Absolutely no WHERE clause. Fetches every single order with deep JOINs on every call.
---
## 5. Product availability (reads ALL products)
Source: `packages/db_helper_sqlite/src/user-apis/slots.ts:29-46``getProductAvailability()`
```sql
select "id", "name", "is_out_of_stock", "is_flash_available"
from "product_info"
where "product_info"."is_suspended" = ?
```
**Why it's bad**: Called on every `getSlotsWithProducts` page load. Reads every non-suspended product even though only products in active slots are relevant.
---
## 6. searchUsers (no search = all users, no limit)
Source: `packages/db_helper_sqlite/src/admin-apis/user.ts:197-216``searchUsers()`
```sql
select "id", "name", "mobile" from "users"
-- no WHERE, no LIMIT
```
**Why it's bad**: When called without a search term, returns the entire `users` table with no limit.
---
## 7. All cache initialization helpers
Source: `packages/db_helper_sqlite/src/stores/store-helpers.ts`
| Function | Line | Query |
|----------|------|-------|
| `getAllProductsForCache` | :86 | `select ... from product_info inner join units` — no WHERE |
| `getAllStoresForCache` | :115 | `select ... from store_info` — no WHERE |
| `getAllProductTagsForCache` | :159 | `select ... from product_tags inner join product_tag_info` — no WHERE |
| `getAllTagsForCache` | :187 | `select ... from product_tag_info` — no WHERE |
| `getAllTagProductMappings` | :200 | `select ... from product_tags` — no WHERE |
| `getAllUserNegativityScores` | :269 | `select ... from user_incidents group by user_id` — no WHERE |
**Why it's bad**: Individually these are meant for cache warming, but they're also called on every cache read miss in `product-store.ts`, doing 5 full table scans per product detail page view.