enh
This commit is contained in:
parent
23be301cc0
commit
17e2644759
130 changed files with 3277 additions and 2266 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
ENV_MODE=PROD
|
ENV_MODE=PROD
|
||||||
DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy
|
# DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy
|
||||||
# DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner
|
# DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner
|
||||||
|
SQLITE_DB_PATH='./sqlite.db'
|
||||||
|
DB_DIALECT='sqlite'
|
||||||
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
|
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
|
||||||
|
|
||||||
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
|
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
|
||||||
PHONE_PE_CLIENT_VERSION=1
|
PHONE_PE_CLIENT_VERSION=1
|
||||||
PHONE_PE_CLIENT_SECRET=MTU1MmIzOTgtM2Q0Mi00N2M5LTkyMWUtNzBiMjdmYzVmZWUy
|
PHONE_PE_CLIENT_SECRET=MTU1MmIzOTgtM2Q0Mi00N2M5LTkyMWUtNzBiMjdmYzVmZWUy
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
import 'dotenv/config';
|
import postgresConfig from '../db-helper-postgres/drizzle.config'
|
||||||
import { defineConfig } from 'drizzle-kit';
|
import sqliteConfig from '../db-helper-sqlite/drizzle.config'
|
||||||
|
|
||||||
export default defineConfig({
|
export default process.env.DB_DIALECT === 'sqlite'
|
||||||
out: './drizzle',
|
? sqliteConfig
|
||||||
schema: './src/db/schema.ts',
|
: postgresConfig
|
||||||
dialect: 'postgresql',
|
|
||||||
dbCredentials: {
|
|
||||||
url: process.env.DATABASE_URL!,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,6 @@ app.onError((err, c) => {
|
||||||
return c.json({ message }, status)
|
return c.json({ message }, status)
|
||||||
})
|
})
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
// Start server
|
// Start server
|
||||||
serve({
|
serve({
|
||||||
fetch: app.fetch,
|
fetch: app.fetch,
|
||||||
|
|
@ -166,8 +165,3 @@ serve({
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('🚀 Server running on http://localhost:4000')
|
console.log('🚀 Server running on http://localhost:4000')
|
||||||
=======
|
|
||||||
app.listen(4000, '::', () => {
|
|
||||||
console.log("Server is running on http://localhost:4000/api/mobile/");
|
|
||||||
});
|
|
||||||
>>>>>>> main
|
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"migrate": "drizzle-kit generate --config drizzle.config.postgres.ts",
|
"migrate": "drizzle-kit generate --config ../db-helper-postgres/drizzle.config.ts",
|
||||||
"migrate:pg": "drizzle-kit generate --config drizzle.config.postgres.ts",
|
"migrate:pg": "drizzle-kit generate --config ../db-helper-postgres/drizzle.config.ts",
|
||||||
"migrate:sqlite": "drizzle-kit generate --config drizzle.config.sqlite.ts",
|
"migrate:sqlite": "drizzle-kit generate --config ../db-helper-sqlite/drizzle.config.ts",
|
||||||
"generate:pg": "bunx drizzle-kit generate --config drizzle.config.postgres.ts",
|
"generate:pg": "bunx drizzle-kit generate --config ../db-helper-postgres/drizzle.config.ts",
|
||||||
"generate:sqlite": "bunx drizzle-kit generate --config drizzle.config.sqlite.ts",
|
"generate:sqlite": "bunx drizzle-kit generate --config ../db-helper-sqlite/drizzle.config.ts",
|
||||||
"build": "rimraf ./dist && tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
|
"build": "rimraf ./dist && tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
|
||||||
"build2": "rimraf ./dist && tsc",
|
"build2": "rimraf ./dist && tsc",
|
||||||
"db:push": "drizzle-kit push --config drizzle.config.postgres.ts",
|
"db:push": "drizzle-kit push --config ../db-helper-postgres/drizzle.config.ts",
|
||||||
"db:push:pg": "drizzle-kit push --config drizzle.config.postgres.ts",
|
"db:push:pg": "drizzle-kit push --config ../db-helper-postgres/drizzle.config.ts",
|
||||||
"db:push:sqlite": "drizzle-kit push --config drizzle.config.sqlite.ts",
|
"db:push:sqlite": "drizzle-kit push --config ../db-helper-sqlite/drizzle.config.ts",
|
||||||
"db:seed": "tsx src/db/seed.ts",
|
"db:seed": "tsx src/db/seed.ts",
|
||||||
"dev:express": "bun --watch index-express.ts",
|
"dev:express": "bun --watch index-express.ts",
|
||||||
"dev:hono": "bun --watch index.ts",
|
"dev:hono": "bun --watch index.ts",
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||
"jose": "^5.10.0",
|
"jose": "^5.10.0",
|
||||||
"node-cron": "^4.2.1",
|
"node-cron": "^4.2.1",
|
||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"razorpay": "^2.9.6",
|
|
||||||
"redis": "^5.9.0",
|
"redis": "^5.9.0",
|
||||||
"zod": "^4.1.12"
|
"zod": "^4.1.12"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
BIN
apps/backend/sqlite.db
Normal file
BIN
apps/backend/sqlite.db
Normal file
Binary file not shown.
|
|
@ -1,85 +1,19 @@
|
||||||
import { eq, gt, and, sql, inArray } from "drizzle-orm";
|
import { Context } from 'hono'
|
||||||
import { Context } from "hono";
|
|
||||||
import { db } from "@/src/db/db_index"
|
|
||||||
import { productInfo, units, productSlots, deliverySlotInfo, productTags } from "@/src/db/schema"
|
|
||||||
import { scaffoldAssetUrl } from "@/src/lib/s3-client"
|
|
||||||
|
|
||||||
/**
|
import { getProductsSummaryData } from '@/src/db/common-product'
|
||||||
* Get next delivery date for a product
|
import { scaffoldAssetUrl } from '@/src/lib/s3-client'
|
||||||
*/
|
|
||||||
const getNextDeliveryDate = async (productId: number): Promise<Date | null> => {
|
|
||||||
const result = await db
|
|
||||||
.select({ deliveryTime: deliverySlotInfo.deliveryTime })
|
|
||||||
.from(productSlots)
|
|
||||||
.innerJoin(deliverySlotInfo, eq(productSlots.slotId, deliverySlotInfo.id))
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(productSlots.productId, productId),
|
|
||||||
eq(deliverySlotInfo.isActive, true),
|
|
||||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.orderBy(deliverySlotInfo.deliveryTime)
|
|
||||||
.limit(1);
|
|
||||||
|
|
||||||
|
|
||||||
return result[0]?.deliveryTime || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all products summary for dropdown
|
* Get all products summary for dropdown
|
||||||
*/
|
*/
|
||||||
export const getAllProductsSummary = async (c: Context) => {
|
export const getAllProductsSummary = async (c: Context) => {
|
||||||
try {
|
try {
|
||||||
const tagId = c.req.query('tagId');
|
const tagId = c.req.query('tagId')
|
||||||
const tagIdNum = tagId ? parseInt(tagId) : null;
|
const tagIdNum = tagId ? parseInt(tagId) : null
|
||||||
|
|
||||||
let productIds: number[] | null = null;
|
const productsWithUnits = await getProductsSummaryData(tagIdNum)
|
||||||
|
|
||||||
// If tagId is provided, get products that have this tag
|
const formattedProducts = productsWithUnits.map((product) => ({
|
||||||
if (tagIdNum) {
|
|
||||||
const taggedProducts = await db
|
|
||||||
.select({ productId: productTags.productId })
|
|
||||||
.from(productTags)
|
|
||||||
.where(eq(productTags.tagId, tagIdNum));
|
|
||||||
|
|
||||||
productIds = taggedProducts.map(tp => tp.productId);
|
|
||||||
}
|
|
||||||
|
|
||||||
let whereCondition = undefined;
|
|
||||||
|
|
||||||
// Filter by product IDs if tag filtering is applied
|
|
||||||
if (productIds && productIds.length > 0) {
|
|
||||||
whereCondition = inArray(productInfo.id, productIds);
|
|
||||||
} else if (tagIdNum) {
|
|
||||||
// If tagId was provided but no products found, return empty array
|
|
||||||
return c.json({
|
|
||||||
products: [],
|
|
||||||
count: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const productsWithUnits = await db
|
|
||||||
.select({
|
|
||||||
id: productInfo.id,
|
|
||||||
name: productInfo.name,
|
|
||||||
shortDescription: productInfo.shortDescription,
|
|
||||||
price: productInfo.price,
|
|
||||||
marketPrice: productInfo.marketPrice,
|
|
||||||
images: productInfo.images,
|
|
||||||
isOutOfStock: productInfo.isOutOfStock,
|
|
||||||
unitShortNotation: units.shortNotation,
|
|
||||||
productQuantity: productInfo.productQuantity,
|
|
||||||
})
|
|
||||||
.from(productInfo)
|
|
||||||
.innerJoin(units, eq(productInfo.unitId, units.id))
|
|
||||||
.where(whereCondition);
|
|
||||||
|
|
||||||
// Generate signed URLs for product images
|
|
||||||
const formattedProducts = await Promise.all(
|
|
||||||
productsWithUnits.map(async (product) => {
|
|
||||||
const nextDeliveryDate = await getNextDeliveryDate(product.id);
|
|
||||||
return {
|
|
||||||
id: product.id,
|
id: product.id,
|
||||||
name: product.name,
|
name: product.name,
|
||||||
shortDescription: product.shortDescription,
|
shortDescription: product.shortDescription,
|
||||||
|
|
@ -88,18 +22,16 @@ export const getAllProductsSummary = async (c: Context) => {
|
||||||
unit: product.unitShortNotation,
|
unit: product.unitShortNotation,
|
||||||
productQuantity: product.productQuantity,
|
productQuantity: product.productQuantity,
|
||||||
isOutOfStock: product.isOutOfStock,
|
isOutOfStock: product.isOutOfStock,
|
||||||
nextDeliveryDate: nextDeliveryDate ? nextDeliveryDate.toISOString() : null,
|
nextDeliveryDate: product.nextDeliveryDate ? product.nextDeliveryDate.toISOString() : null,
|
||||||
images: scaffoldAssetUrl((product.images as string[]) || []),
|
images: scaffoldAssetUrl((product.images as string[]) || []),
|
||||||
};
|
}))
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return c.json({
|
return c.json({
|
||||||
products: formattedProducts,
|
products: formattedProducts,
|
||||||
count: formattedProducts.length,
|
count: formattedProducts.length,
|
||||||
});
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Get products summary error:", error);
|
console.error('Get products summary error:', error)
|
||||||
return c.json({ error: "Failed to fetch products summary" }, 500);
|
return c.json({ error: 'Failed to fetch products summary' }, 500)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
||||||
10
apps/backend/src/db/common-product.ts
Normal file
10
apps/backend/src/db/common-product.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { getProductsSummaryData as getProductsSummaryDataPostgres } from '@db-helper-postgres/apis/common-apis/common-product'
|
||||||
|
import { getProductsSummaryData as getProductsSummaryDataSqlite } from '@db-helper-sqlite/apis/common-apis/common-product'
|
||||||
|
|
||||||
|
const dialect = process.env.DB_DIALECT || DB_DIALECT_TYPE
|
||||||
|
|
||||||
|
const getProductsSummaryData = dialect === 'sqlite'
|
||||||
|
? getProductsSummaryDataSqlite
|
||||||
|
: getProductsSummaryDataPostgres
|
||||||
|
|
||||||
|
export { getProductsSummaryData }
|
||||||
14
apps/backend/src/db/db_index.ts
Executable file → Normal file
14
apps/backend/src/db/db_index.ts
Executable file → Normal file
|
|
@ -1,8 +1,10 @@
|
||||||
import { drizzle } from "drizzle-orm/node-postgres"
|
import { db as postgresDb } from '@db-helper-postgres/db/db_index'
|
||||||
import { migrate } from "drizzle-orm/node-postgres/migrator"
|
import { db as sqliteDb } from '@db-helper-sqlite/db/db_index'
|
||||||
import path from "path"
|
|
||||||
import * as schema from "@/src/db/schema-postgres"
|
const dialect = process.env.DB_DIALECT || DB_DIALECT_TYPE
|
||||||
|
|
||||||
|
type Db = typeof DB_DIALECT_TYPE extends 'sqlite' ? typeof sqliteDb : typeof postgresDb
|
||||||
|
|
||||||
|
const db = (dialect === 'sqlite' ? sqliteDb : postgresDb) as Db
|
||||||
|
|
||||||
const db = drizzle({ connection: process.env.DATABASE_URL!, casing: "snake_case", schema: schema })
|
|
||||||
// const db = drizzle('postgresql://postgres:postgres@localhost:2345/pooler');
|
|
||||||
export { db }
|
export { db }
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
import { drizzle } from 'drizzle-orm/bun-sqlite'
|
|
||||||
import { Database } from 'bun:sqlite'
|
|
||||||
import * as schema from '@/src/db/schema-sqlite'
|
|
||||||
|
|
||||||
const sqlitePath = process.env.SQLITE_DB_PATH || 'sqlite.db'
|
|
||||||
const sqlite = new Database(sqlitePath)
|
|
||||||
|
|
||||||
const db = drizzle(sqlite, { schema })
|
|
||||||
|
|
||||||
export { db }
|
|
||||||
|
|
@ -1,706 +1 @@
|
||||||
import { pgTable, pgSchema, integer, varchar, date, boolean, timestamp, numeric, jsonb, pgEnum, unique, real, text, check, decimal } from "drizzle-orm/pg-core";
|
export * from '@/db-helper-postgres/db/schema'
|
||||||
import { relations, sql } from "drizzle-orm";
|
|
||||||
|
|
||||||
const mf = pgSchema('mf');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const users = mf.table('users', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar({ length: 255 }),
|
|
||||||
email: varchar({ length: 255 }),
|
|
||||||
mobile: varchar({ length: 255 }),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_email: unique('unique_email').on(t.email),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userDetails = mf.table('user_details', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id).unique(),
|
|
||||||
bio: varchar('bio', { length: 500 }),
|
|
||||||
dateOfBirth: date('date_of_birth'),
|
|
||||||
gender: varchar('gender', { length: 20 }),
|
|
||||||
occupation: varchar('occupation', { length: 100 }),
|
|
||||||
profileImage: varchar('profile_image', { length: 500 }),
|
|
||||||
isSuspended: boolean('is_suspended').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
updatedAt: timestamp('updated_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const userCreds = mf.table('user_creds', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
userPassword: varchar('user_password', { length: 255 }).notNull(),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const addresses = mf.table('addresses', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
name: varchar('name', { length: 255 }).notNull(),
|
|
||||||
phone: varchar('phone', { length: 15 }).notNull(),
|
|
||||||
addressLine1: varchar('address_line1', { length: 255 }).notNull(),
|
|
||||||
addressLine2: varchar('address_line2', { length: 255 }),
|
|
||||||
city: varchar('city', { length: 100 }).notNull(),
|
|
||||||
state: varchar('state', { length: 100 }).notNull(),
|
|
||||||
pincode: varchar('pincode', { length: 10 }).notNull(),
|
|
||||||
isDefault: boolean('is_default').notNull().default(false),
|
|
||||||
latitude: real('latitude'),
|
|
||||||
longitude: real('longitude'),
|
|
||||||
googleMapsUrl: varchar('google_maps_url', { length: 500 }),
|
|
||||||
adminLatitude: real('admin_latitude'),
|
|
||||||
adminLongitude: real('admin_longitude'),
|
|
||||||
zoneId: integer('zone_id').references(() => addressZones.id),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const addressZones = mf.table('address_zones', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
zoneName: varchar('zone_name', { length: 255 }).notNull(),
|
|
||||||
addedAt: timestamp('added_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const addressAreas = mf.table('address_areas', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
placeName: varchar('place_name', { length: 255 }).notNull(),
|
|
||||||
zoneId: integer('zone_id').references(() => addressZones.id),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const staffUsers = mf.table('staff_users', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar({ length: 255 }).notNull(),
|
|
||||||
password: varchar({ length: 255 }).notNull(),
|
|
||||||
staffRoleId: integer('staff_role_id').references(() => staffRoles.id),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const storeInfo = mf.table('store_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar({ length: 255 }).notNull(),
|
|
||||||
description: varchar({ length: 500 }),
|
|
||||||
imageUrl: varchar('image_url', { length: 500 }),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
owner: integer('owner').notNull().references(() => staffUsers.id),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const units = mf.table('units', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
shortNotation: varchar('short_notation', { length: 50 }).notNull(),
|
|
||||||
fullName: varchar('full_name', { length: 100 }).notNull(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_short_notation: unique('unique_short_notation').on(t.shortNotation),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productAvailabilityActionEnum = pgEnum('product_availability_action', ['in', 'out']);
|
|
||||||
|
|
||||||
export const productInfo = mf.table('product_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar({ length: 255 }).notNull(),
|
|
||||||
shortDescription: varchar('short_description', { length: 500 }),
|
|
||||||
longDescription: varchar('long_description', { length: 1000 }),
|
|
||||||
unitId: integer('unit_id').notNull().references(() => units.id),
|
|
||||||
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
|
||||||
marketPrice: numeric('market_price', { precision: 10, scale: 2 }),
|
|
||||||
images: jsonb('images'),
|
|
||||||
isOutOfStock: boolean('is_out_of_stock').notNull().default(false),
|
|
||||||
isSuspended: boolean('is_suspended').notNull().default(false),
|
|
||||||
isFlashAvailable: boolean('is_flash_available').notNull().default(false),
|
|
||||||
flashPrice: numeric('flash_price', { precision: 10, scale: 2 }),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
incrementStep: real('increment_step').notNull().default(1),
|
|
||||||
productQuantity: real('product_quantity').notNull().default(1),
|
|
||||||
storeId: integer('store_id').references(() => storeInfo.id),
|
|
||||||
scheduledAvailability: boolean('scheduled_availability').notNull().default(true),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productAvailabilitySchedules = mf.table('product_availability_schedules', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
time: varchar('time', { length: 10 }).notNull(),
|
|
||||||
scheduleName: varchar('schedule_name', { length: 255 }).notNull().unique(),
|
|
||||||
action: productAvailabilityActionEnum('action').notNull(),
|
|
||||||
productIds: integer('product_ids').array().notNull().default([]),
|
|
||||||
groupIds: integer('group_ids').array().notNull().default([]),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
lastUpdated: timestamp('last_updated').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productGroupInfo = mf.table('product_group_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
groupName: varchar('group_name', { length: 255 }).notNull(),
|
|
||||||
description: varchar({ length: 500 }),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productGroupMembership = mf.table('product_group_membership', {
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
groupId: integer('group_id').notNull().references(() => productGroupInfo.id),
|
|
||||||
addedAt: timestamp('added_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
pk: unique('product_group_membership_pk').on(t.productId, t.groupId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const homeBanners = mf.table('home_banners', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar('name', { length: 255 }).notNull(),
|
|
||||||
imageUrl: varchar('image_url', { length: 500 }).notNull(),
|
|
||||||
description: varchar('description', { length: 500 }),
|
|
||||||
productIds: integer('product_ids').array(),
|
|
||||||
redirectUrl: varchar('redirect_url', { length: 500 }),
|
|
||||||
serialNum: integer('serial_num'),
|
|
||||||
isActive: boolean('is_active').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
lastUpdated: timestamp('last_updated').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productReviews = mf.table('product_reviews', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
reviewBody: text('review_body').notNull(),
|
|
||||||
imageUrls: jsonb('image_urls').$defaultFn(() => []),
|
|
||||||
reviewTime: timestamp('review_time').notNull().defaultNow(),
|
|
||||||
ratings: real('ratings').notNull(),
|
|
||||||
adminResponse: text('admin_response'),
|
|
||||||
adminResponseImages: jsonb('admin_response_images').$defaultFn(() => []),
|
|
||||||
}, (t) => ({
|
|
||||||
ratingCheck: check('rating_check', sql`${t.ratings} >= 1 AND ${t.ratings} <= 5`),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const uploadStatusEnum = pgEnum('upload_status', ['pending', 'claimed']);
|
|
||||||
|
|
||||||
export const staffRoleEnum = pgEnum('staff_role', ['super_admin', 'admin', 'marketer', 'delivery_staff']);
|
|
||||||
|
|
||||||
export const staffPermissionEnum = pgEnum('staff_permission', ['crud_product', 'make_coupon', 'crud_staff_users']);
|
|
||||||
|
|
||||||
export const uploadUrlStatus = mf.table('upload_url_status', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
key: varchar('key', { length: 500 }).notNull(),
|
|
||||||
status: uploadStatusEnum('status').notNull().default('pending'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productTagInfo = mf.table('product_tag_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
tagName: varchar('tag_name', { length: 100 }).notNull().unique(),
|
|
||||||
tagDescription: varchar('tag_description', { length: 500 }),
|
|
||||||
imageUrl: varchar('image_url', { length: 500 }),
|
|
||||||
isDashboardTag: boolean('is_dashboard_tag').notNull().default(false),
|
|
||||||
relatedStores: jsonb('related_stores').$defaultFn(() => []),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productTags = mf.table('product_tags', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
tagId: integer('tag_id').notNull().references(() => productTagInfo.id),
|
|
||||||
assignedAt: timestamp('assigned_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_product_tag: unique('unique_product_tag').on(t.productId, t.tagId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const deliverySlotInfo = mf.table('delivery_slot_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
deliveryTime: timestamp('delivery_time').notNull(),
|
|
||||||
freezeTime: timestamp('freeze_time').notNull(),
|
|
||||||
isActive: boolean('is_active').notNull().default(true),
|
|
||||||
isFlash: boolean('is_flash').notNull().default(false),
|
|
||||||
isCapacityFull: boolean('is_capacity_full').notNull().default(false),
|
|
||||||
deliverySequence: jsonb('delivery_sequence').$defaultFn(() => {}),
|
|
||||||
groupIds: jsonb('group_ids').$defaultFn(() => []),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const vendorSnippets = mf.table('vendor_snippets', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
snippetCode: varchar('snippet_code', { length: 255 }).notNull().unique(),
|
|
||||||
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
|
||||||
isPermanent: boolean('is_permanent').notNull().default(false),
|
|
||||||
productIds: integer('product_ids').array().notNull(),
|
|
||||||
validTill: timestamp('valid_till'),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const vendorSnippetsRelations = relations(vendorSnippets, ({ one }) => ({
|
|
||||||
slot: one(deliverySlotInfo, { fields: [vendorSnippets.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productSlots = mf.table('product_slots', {
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
slotId: integer('slot_id').notNull().references(() => deliverySlotInfo.id),
|
|
||||||
}, (t) => ({
|
|
||||||
pk: unique('product_slot_pk').on(t.productId, t.slotId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const specialDeals = mf.table('special_deals', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: numeric({ precision: 10, scale: 2 }).notNull(),
|
|
||||||
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
|
||||||
validTill: timestamp('valid_till').notNull(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const orders = mf.table('orders', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
addressId: integer('address_id').notNull().references(() => addresses.id),
|
|
||||||
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
|
||||||
isCod: boolean('is_cod').notNull().default(false),
|
|
||||||
isOnlinePayment: boolean('is_online_payment').notNull().default(false),
|
|
||||||
paymentInfoId: integer('payment_info_id').references(() => paymentInfoTable.id),
|
|
||||||
totalAmount: numeric('total_amount', { precision: 10, scale: 2 }).notNull(),
|
|
||||||
deliveryCharge: numeric('delivery_charge', { precision: 10, scale: 2 }).notNull().default('0'),
|
|
||||||
readableId: integer('readable_id').notNull(),
|
|
||||||
adminNotes: text('admin_notes'),
|
|
||||||
userNotes: text('user_notes'),
|
|
||||||
orderGroupId: varchar('order_group_id', { length: 255 }),
|
|
||||||
orderGroupProportion: decimal('order_group_proportion', { precision: 10, scale: 4 }),
|
|
||||||
isFlashDelivery: boolean('is_flash_delivery').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const orderItems = mf.table('order_items', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: varchar('quantity', { length: 50 }).notNull(),
|
|
||||||
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
|
||||||
discountedPrice: numeric('discounted_price', { precision: 10, scale: 2 }),
|
|
||||||
is_packaged: boolean('is_packaged').notNull().default(false),
|
|
||||||
is_package_verified: boolean('is_package_verified').notNull().default(false),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const paymentStatusEnum = pgEnum('payment_status', ['pending', 'success', 'cod', 'failed']);
|
|
||||||
|
|
||||||
export const orderStatus = mf.table('order_status', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
orderTime: timestamp('order_time').notNull().defaultNow(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
isPackaged: boolean('is_packaged').notNull().default(false),
|
|
||||||
isDelivered: boolean('is_delivered').notNull().default(false),
|
|
||||||
isCancelled: boolean('is_cancelled').notNull().default(false),
|
|
||||||
cancelReason: varchar('cancel_reason', { length: 255 }),
|
|
||||||
isCancelledByAdmin: boolean('is_cancelled_by_admin'),
|
|
||||||
paymentStatus: paymentStatusEnum('payment_state').notNull().default('pending'),
|
|
||||||
cancellationUserNotes: text('cancellation_user_notes'),
|
|
||||||
cancellationAdminNotes: text('cancellation_admin_notes'),
|
|
||||||
cancellationReviewed: boolean('cancellation_reviewed').notNull().default(false),
|
|
||||||
cancellationReviewedAt: timestamp('cancellation_reviewed_at'),
|
|
||||||
refundCouponId: integer('refund_coupon_id').references(() => coupons.id),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const paymentInfoTable = mf.table('payment_info', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
status: varchar({ length: 50 }).notNull(),
|
|
||||||
gateway: varchar({ length: 50 }).notNull(),
|
|
||||||
orderId: varchar('order_id', { length: 500 }),
|
|
||||||
token: varchar({ length: 500 }),
|
|
||||||
merchantOrderId: varchar('merchant_order_id', { length: 255 }).notNull().unique(),
|
|
||||||
payload: jsonb('payload'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const payments = mf.table('payments', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
status: varchar({ length: 50 }).notNull(),
|
|
||||||
gateway: varchar({ length: 50 }).notNull(),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
token: varchar({ length: 500 }),
|
|
||||||
merchantOrderId: varchar('merchant_order_id', { length: 255 }).notNull().unique(),
|
|
||||||
payload: jsonb('payload'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const refunds = mf.table('refunds', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
refundAmount: numeric('refund_amount', { precision: 10, scale: 2 }),
|
|
||||||
refundStatus: varchar('refund_status', { length: 50 }).default('none'),
|
|
||||||
merchantRefundId: varchar('merchant_refund_id', { length: 255 }),
|
|
||||||
refundProcessedAt: timestamp('refund_processed_at'),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const keyValStore = mf.table('key_val_store', {
|
|
||||||
key: varchar('key', { length: 255 }).primaryKey(),
|
|
||||||
value: jsonb('value'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const notifications = mf.table('notifications', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
title: varchar({ length: 255 }).notNull(),
|
|
||||||
body: varchar({ length: 512 }).notNull(),
|
|
||||||
type: varchar({ length: 50 }),
|
|
||||||
isRead: boolean('is_read').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const productCategories = mf.table('product_categories', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
name: varchar({ length: 255 }).notNull(),
|
|
||||||
description: varchar({ length: 500 }),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const cartItems = mf.table('cart_items', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: numeric({ precision: 10, scale: 2 }).notNull(),
|
|
||||||
addedAt: timestamp('added_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_user_product: unique('unique_user_product').on(t.userId, t.productId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const complaints = mf.table('complaints', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
complaintBody: varchar('complaint_body', { length: 1000 }).notNull(),
|
|
||||||
images: jsonb('images'),
|
|
||||||
response: varchar('response', { length: 1000 }),
|
|
||||||
isResolved: boolean('is_resolved').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const coupons = mf.table('coupons', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
couponCode: varchar('coupon_code', { length: 50 }).notNull().unique('unique_coupon_code'),
|
|
||||||
isUserBased: boolean('is_user_based').notNull().default(false),
|
|
||||||
discountPercent: numeric('discount_percent', { precision: 5, scale: 2 }),
|
|
||||||
flatDiscount: numeric('flat_discount', { precision: 10, scale: 2 }),
|
|
||||||
minOrder: numeric('min_order', { precision: 10, scale: 2 }),
|
|
||||||
productIds: jsonb('product_ids'),
|
|
||||||
createdBy: integer('created_by').references(() => staffUsers.id),
|
|
||||||
maxValue: numeric('max_value', { precision: 10, scale: 2 }),
|
|
||||||
isApplyForAll: boolean('is_apply_for_all').notNull().default(false),
|
|
||||||
validTill: timestamp('valid_till'),
|
|
||||||
maxLimitForUser: integer('max_limit_for_user'),
|
|
||||||
isInvalidated: boolean('is_invalidated').notNull().default(false),
|
|
||||||
exclusiveApply: boolean('exclusive_apply').notNull().default(false),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const couponUsage = mf.table('coupon_usage', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
orderItemId: integer('order_item_id').references(() => orderItems.id),
|
|
||||||
usedAt: timestamp('used_at').notNull().defaultNow(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const couponApplicableUsers = mf.table('coupon_applicable_users', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_coupon_user: unique('unique_coupon_user').on(t.couponId, t.userId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const couponApplicableProducts = mf.table('coupon_applicable_products', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_coupon_product: unique('unique_coupon_product').on(t.couponId, t.productId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userIncidents = mf.table('user_incidents', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
dateAdded: timestamp('date_added').notNull().defaultNow(),
|
|
||||||
adminComment: text('admin_comment'),
|
|
||||||
addedBy: integer('added_by').references(() => staffUsers.id),
|
|
||||||
negativityScore: integer('negativity_score'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const reservedCoupons = mf.table('reserved_coupons', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
secretCode: varchar('secret_code', { length: 50 }).notNull().unique(),
|
|
||||||
couponCode: varchar('coupon_code', { length: 50 }).notNull(),
|
|
||||||
discountPercent: numeric('discount_percent', { precision: 5, scale: 2 }),
|
|
||||||
flatDiscount: numeric('flat_discount', { precision: 10, scale: 2 }),
|
|
||||||
minOrder: numeric('min_order', { precision: 10, scale: 2 }),
|
|
||||||
productIds: jsonb('product_ids'),
|
|
||||||
maxValue: numeric('max_value', { precision: 10, scale: 2 }),
|
|
||||||
validTill: timestamp('valid_till'),
|
|
||||||
maxLimitForUser: integer('max_limit_for_user'),
|
|
||||||
exclusiveApply: boolean('exclusive_apply').notNull().default(false),
|
|
||||||
isRedeemed: boolean('is_redeemed').notNull().default(false),
|
|
||||||
redeemedBy: integer('redeemed_by').references(() => users.id),
|
|
||||||
redeemedAt: timestamp('redeemed_at'),
|
|
||||||
createdBy: integer('created_by').notNull().references(() => staffUsers.id),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_secret_code: unique('unique_secret_code').on(t.secretCode),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const notifCreds = mf.table('notif_creds', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
token: varchar({ length: 500 }).notNull().unique(),
|
|
||||||
addedAt: timestamp('added_at').notNull().defaultNow(),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
lastVerified: timestamp('last_verified'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const unloggedUserTokens = mf.table('unlogged_user_tokens', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
token: varchar({ length: 500 }).notNull().unique(),
|
|
||||||
addedAt: timestamp('added_at').notNull().defaultNow(),
|
|
||||||
lastVerified: timestamp('last_verified'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const userNotifications = mf.table('user_notifications', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
title: varchar('title', { length: 255 }).notNull(),
|
|
||||||
imageUrl: varchar('image_url', { length: 500 }),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
body: text('body').notNull(),
|
|
||||||
applicableUsers: jsonb('applicable_users'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const staffRoles = mf.table('staff_roles', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
roleName: staffRoleEnum('role_name').notNull(),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_role_name: unique('unique_role_name').on(t.roleName),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffPermissions = mf.table('staff_permissions', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
permissionName: staffPermissionEnum('permission_name').notNull(),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_permission_name: unique('unique_permission_name').on(t.permissionName),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffRolePermissions = mf.table('staff_role_permissions', {
|
|
||||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
|
||||||
staffRoleId: integer('staff_role_id').notNull().references(() => staffRoles.id),
|
|
||||||
staffPermissionId: integer('staff_permission_id').notNull().references(() => staffPermissions.id),
|
|
||||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_role_permission: unique('unique_role_permission').on(t.staffRoleId, t.staffPermissionId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Relations
|
|
||||||
export const usersRelations = relations(users, ({ many, one }) => ({
|
|
||||||
addresses: many(addresses),
|
|
||||||
orders: many(orders),
|
|
||||||
notifications: many(notifications),
|
|
||||||
cartItems: many(cartItems),
|
|
||||||
userCreds: one(userCreds),
|
|
||||||
coupons: many(coupons),
|
|
||||||
couponUsages: many(couponUsage),
|
|
||||||
applicableCoupons: many(couponApplicableUsers),
|
|
||||||
userDetails: one(userDetails),
|
|
||||||
notifCreds: many(notifCreds),
|
|
||||||
userIncidents: many(userIncidents),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userCredsRelations = relations(userCreds, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userCreds.userId], references: [users.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffUsersRelations = relations(staffUsers, ({ one, many }) => ({
|
|
||||||
role: one(staffRoles, { fields: [staffUsers.staffRoleId], references: [staffRoles.id] }),
|
|
||||||
coupons: many(coupons),
|
|
||||||
stores: many(storeInfo),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const addressesRelations = relations(addresses, ({ one, many }) => ({
|
|
||||||
user: one(users, { fields: [addresses.userId], references: [users.id] }),
|
|
||||||
orders: many(orders),
|
|
||||||
zone: one(addressZones, { fields: [addresses.zoneId], references: [addressZones.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const unitsRelations = relations(units, ({ many }) => ({
|
|
||||||
products: many(productInfo),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productInfoRelations = relations(productInfo, ({ one, many }) => ({
|
|
||||||
unit: one(units, { fields: [productInfo.unitId], references: [units.id] }),
|
|
||||||
store: one(storeInfo, { fields: [productInfo.storeId], references: [storeInfo.id] }),
|
|
||||||
productSlots: many(productSlots),
|
|
||||||
specialDeals: many(specialDeals),
|
|
||||||
orderItems: many(orderItems),
|
|
||||||
cartItems: many(cartItems),
|
|
||||||
tags: many(productTags),
|
|
||||||
applicableCoupons: many(couponApplicableProducts),
|
|
||||||
reviews: many(productReviews),
|
|
||||||
groups: many(productGroupMembership),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productTagInfoRelations = relations(productTagInfo, ({ many }) => ({
|
|
||||||
products: many(productTags),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productTagsRelations = relations(productTags, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productTags.productId], references: [productInfo.id] }),
|
|
||||||
tag: one(productTagInfo, { fields: [productTags.tagId], references: [productTagInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const deliverySlotInfoRelations = relations(deliverySlotInfo, ({ many }) => ({
|
|
||||||
productSlots: many(productSlots),
|
|
||||||
orders: many(orders),
|
|
||||||
vendorSnippets: many(vendorSnippets),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productSlotsRelations = relations(productSlots, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productSlots.productId], references: [productInfo.id] }),
|
|
||||||
slot: one(deliverySlotInfo, { fields: [productSlots.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const specialDealsRelations = relations(specialDeals, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [specialDeals.productId], references: [productInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const ordersRelations = relations(orders, ({ one, many }) => ({
|
|
||||||
user: one(users, { fields: [orders.userId], references: [users.id] }),
|
|
||||||
address: one(addresses, { fields: [orders.addressId], references: [addresses.id] }),
|
|
||||||
slot: one(deliverySlotInfo, { fields: [orders.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
orderItems: many(orderItems),
|
|
||||||
payment: one(payments),
|
|
||||||
paymentInfo: one(paymentInfoTable, { fields: [orders.paymentInfoId], references: [paymentInfoTable.id] }),
|
|
||||||
orderStatus: many(orderStatus),
|
|
||||||
refunds: many(refunds),
|
|
||||||
couponUsages: many(couponUsage),
|
|
||||||
userIncidents: many(userIncidents),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const orderItemsRelations = relations(orderItems, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [orderItems.orderId], references: [orders.id] }),
|
|
||||||
product: one(productInfo, { fields: [orderItems.productId], references: [productInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const orderStatusRelations = relations(orderStatus, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [orderStatus.orderId], references: [orders.id] }),
|
|
||||||
user: one(users, { fields: [orderStatus.userId], references: [users.id] }),
|
|
||||||
refundCoupon: one(coupons, { fields: [orderStatus.refundCouponId], references: [coupons.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const paymentInfoRelations = relations(paymentInfoTable, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [paymentInfoTable.id], references: [orders.paymentInfoId] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const paymentsRelations = relations(payments, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [payments.orderId], references: [orders.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const refundsRelations = relations(refunds, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [refunds.orderId], references: [orders.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [notifications.userId], references: [users.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productCategoriesRelations = relations(productCategories, ({}) => ({}));
|
|
||||||
|
|
||||||
export const cartItemsRelations = relations(cartItems, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [cartItems.userId], references: [users.id] }),
|
|
||||||
product: one(productInfo, { fields: [cartItems.productId], references: [productInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const complaintsRelations = relations(complaints, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [complaints.userId], references: [users.id] }),
|
|
||||||
order: one(orders, { fields: [complaints.orderId], references: [orders.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const couponsRelations = relations(coupons, ({ one, many }) => ({
|
|
||||||
creator: one(staffUsers, { fields: [coupons.createdBy], references: [staffUsers.id] }),
|
|
||||||
usages: many(couponUsage),
|
|
||||||
applicableUsers: many(couponApplicableUsers),
|
|
||||||
applicableProducts: many(couponApplicableProducts),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const couponUsageRelations = relations(couponUsage, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [couponUsage.userId], references: [users.id] }),
|
|
||||||
coupon: one(coupons, { fields: [couponUsage.couponId], references: [coupons.id] }),
|
|
||||||
order: one(orders, { fields: [couponUsage.orderId], references: [orders.id] }),
|
|
||||||
orderItem: one(orderItems, { fields: [couponUsage.orderItemId], references: [orderItems.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userDetailsRelations = relations(userDetails, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userDetails.userId], references: [users.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const notifCredsRelations = relations(notifCreds, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [notifCreds.userId], references: [users.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userNotificationsRelations = relations(userNotifications, ({}) => ({
|
|
||||||
// No relations needed for now
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const storeInfoRelations = relations(storeInfo, ({ one, many }) => ({
|
|
||||||
owner: one(staffUsers, { fields: [storeInfo.owner], references: [staffUsers.id] }),
|
|
||||||
products: many(productInfo),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const couponApplicableUsersRelations = relations(couponApplicableUsers, ({ one }) => ({
|
|
||||||
coupon: one(coupons, { fields: [couponApplicableUsers.couponId], references: [coupons.id] }),
|
|
||||||
user: one(users, { fields: [couponApplicableUsers.userId], references: [users.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const couponApplicableProductsRelations = relations(couponApplicableProducts, ({ one }) => ({
|
|
||||||
coupon: one(coupons, { fields: [couponApplicableProducts.couponId], references: [coupons.id] }),
|
|
||||||
product: one(productInfo, { fields: [couponApplicableProducts.productId], references: [productInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const reservedCouponsRelations = relations(reservedCoupons, ({ one }) => ({
|
|
||||||
redeemedUser: one(users, { fields: [reservedCoupons.redeemedBy], references: [users.id] }),
|
|
||||||
creator: one(staffUsers, { fields: [reservedCoupons.createdBy], references: [staffUsers.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productReviewsRelations = relations(productReviews, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [productReviews.userId], references: [users.id] }),
|
|
||||||
product: one(productInfo, { fields: [productReviews.productId], references: [productInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const addressZonesRelations = relations(addressZones, ({ many }) => ({
|
|
||||||
addresses: many(addresses),
|
|
||||||
areas: many(addressAreas),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const addressAreasRelations = relations(addressAreas, ({ one }) => ({
|
|
||||||
zone: one(addressZones, { fields: [addressAreas.zoneId], references: [addressZones.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productGroupInfoRelations = relations(productGroupInfo, ({ many }) => ({
|
|
||||||
memberships: many(productGroupMembership),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productGroupMembershipRelations = relations(productGroupMembership, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productGroupMembership.productId], references: [productInfo.id] }),
|
|
||||||
group: one(productGroupInfo, { fields: [productGroupMembership.groupId], references: [productGroupInfo.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const homeBannersRelations = relations(homeBanners, ({}) => ({
|
|
||||||
// Relations for productIds array would be more complex, skipping for now
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffRolesRelations = relations(staffRoles, ({ many }) => ({
|
|
||||||
staffUsers: many(staffUsers),
|
|
||||||
rolePermissions: many(staffRolePermissions),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffPermissionsRelations = relations(staffPermissions, ({ many }) => ({
|
|
||||||
rolePermissions: many(staffRolePermissions),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const staffRolePermissionsRelations = relations(staffRolePermissions, ({ one }) => ({
|
|
||||||
role: one(staffRoles, { fields: [staffRolePermissions.staffRoleId], references: [staffRoles.id] }),
|
|
||||||
permission: one(staffPermissions, { fields: [staffRolePermissions.staffPermissionId], references: [staffPermissions.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const userIncidentsRelations = relations(userIncidents, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userIncidents.userId], references: [users.id] }),
|
|
||||||
order: one(orders, { fields: [userIncidents.orderId], references: [orders.id] }),
|
|
||||||
addedBy: one(staffUsers, { fields: [userIncidents.addedBy], references: [staffUsers.id] }),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const productAvailabilitySchedulesRelations = relations(productAvailabilitySchedules, ({}) => ({
|
|
||||||
}));
|
|
||||||
|
|
|
||||||
|
|
@ -1,735 +1 @@
|
||||||
import {
|
export * from '@/db-helper-sqlite/db/schema'
|
||||||
sqliteTable,
|
|
||||||
integer,
|
|
||||||
text,
|
|
||||||
real,
|
|
||||||
unique,
|
|
||||||
check,
|
|
||||||
} from 'drizzle-orm/sqlite-core'
|
|
||||||
import { relations, sql } from 'drizzle-orm'
|
|
||||||
|
|
||||||
const epochSeconds = sql`(strftime('%s','now'))`
|
|
||||||
|
|
||||||
const sqliteEnum = <T extends readonly [string, ...string[]]>(
|
|
||||||
_name: string,
|
|
||||||
values: T
|
|
||||||
) => (columnName: string) => text(columnName, { enum: values })
|
|
||||||
|
|
||||||
export const users = sqliteTable('users', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name'),
|
|
||||||
email: text('email'),
|
|
||||||
mobile: text('mobile'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_email: unique('unique_email').on(t.email),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const userDetails = sqliteTable('user_details', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id).unique(),
|
|
||||||
bio: text('bio'),
|
|
||||||
dateOfBirth: integer('date_of_birth', { mode: 'timestamp' }),
|
|
||||||
gender: text('gender'),
|
|
||||||
occupation: text('occupation'),
|
|
||||||
profileImage: text('profile_image'),
|
|
||||||
isSuspended: integer('is_suspended', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const userCreds = sqliteTable('user_creds', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
userPassword: text('user_password').notNull(),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const addressZones = sqliteTable('address_zones', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
zoneName: text('zone_name').notNull(),
|
|
||||||
addedAt: integer('added_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const addresses = sqliteTable('addresses', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
phone: text('phone').notNull(),
|
|
||||||
addressLine1: text('address_line1').notNull(),
|
|
||||||
addressLine2: text('address_line2'),
|
|
||||||
city: text('city').notNull(),
|
|
||||||
state: text('state').notNull(),
|
|
||||||
pincode: text('pincode').notNull(),
|
|
||||||
isDefault: integer('is_default', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
latitude: real('latitude'),
|
|
||||||
longitude: real('longitude'),
|
|
||||||
googleMapsUrl: text('google_maps_url'),
|
|
||||||
adminLatitude: real('admin_latitude'),
|
|
||||||
adminLongitude: real('admin_longitude'),
|
|
||||||
zoneId: integer('zone_id').references(() => addressZones.id),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const addressAreas = sqliteTable('address_areas', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
placeName: text('place_name').notNull(),
|
|
||||||
zoneId: integer('zone_id').references(() => addressZones.id),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const staffRoleEnum = sqliteEnum('staff_role', [
|
|
||||||
'super_admin',
|
|
||||||
'admin',
|
|
||||||
'marketer',
|
|
||||||
'delivery_staff',
|
|
||||||
])
|
|
||||||
|
|
||||||
export const staffPermissionEnum = sqliteEnum('staff_permission', [
|
|
||||||
'crud_product',
|
|
||||||
'make_coupon',
|
|
||||||
'crud_staff_users',
|
|
||||||
])
|
|
||||||
|
|
||||||
export const staffRoles = sqliteTable('staff_roles', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
roleName: staffRoleEnum('role_name').notNull(),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_role_name: unique('unique_role_name').on(t.roleName),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffPermissions = sqliteTable('staff_permissions', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
permissionName: staffPermissionEnum('permission_name').notNull(),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_permission_name: unique('unique_permission_name').on(t.permissionName),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffRolePermissions = sqliteTable('staff_role_permissions', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
staffRoleId: integer('staff_role_id').notNull().references(() => staffRoles.id),
|
|
||||||
staffPermissionId: integer('staff_permission_id').notNull().references(() => staffPermissions.id),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_role_permission: unique('unique_role_permission').on(
|
|
||||||
t.staffRoleId,
|
|
||||||
t.staffPermissionId
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffUsers = sqliteTable('staff_users', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
password: text('password').notNull(),
|
|
||||||
staffRoleId: integer('staff_role_id').references(() => staffRoles.id),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const storeInfo = sqliteTable('store_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
description: text('description'),
|
|
||||||
imageUrl: text('image_url'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
owner: integer('owner').notNull().references(() => staffUsers.id),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const units = sqliteTable('units', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
shortNotation: text('short_notation').notNull(),
|
|
||||||
fullName: text('full_name').notNull(),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_short_notation: unique('unique_short_notation').on(t.shortNotation),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productAvailabilityActionEnum = sqliteEnum(
|
|
||||||
'product_availability_action',
|
|
||||||
['in', 'out']
|
|
||||||
)
|
|
||||||
|
|
||||||
export const productInfo = sqliteTable('product_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
shortDescription: text('short_description'),
|
|
||||||
longDescription: text('long_description'),
|
|
||||||
unitId: integer('unit_id').notNull().references(() => units.id),
|
|
||||||
price: text('price').notNull(),
|
|
||||||
marketPrice: text('market_price'),
|
|
||||||
images: text('images'),
|
|
||||||
isOutOfStock: integer('is_out_of_stock', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isSuspended: integer('is_suspended', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isFlashAvailable: integer('is_flash_available', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
flashPrice: text('flash_price'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
incrementStep: real('increment_step').notNull().default(1),
|
|
||||||
productQuantity: real('product_quantity').notNull().default(1),
|
|
||||||
storeId: integer('store_id').references(() => storeInfo.id),
|
|
||||||
scheduledAvailability: integer('scheduled_availability', { mode: 'boolean' }).notNull().default(true),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productAvailabilitySchedules = sqliteTable('product_availability_schedules', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
time: text('time').notNull(),
|
|
||||||
scheduleName: text('schedule_name').notNull().unique(),
|
|
||||||
action: productAvailabilityActionEnum('action').notNull(),
|
|
||||||
productIds: text('product_ids').notNull().default('[]'),
|
|
||||||
groupIds: text('group_ids').notNull().default('[]'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
lastUpdated: integer('last_updated', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productGroupInfo = sqliteTable('product_group_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
groupName: text('group_name').notNull(),
|
|
||||||
description: text('description'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productGroupMembership = sqliteTable('product_group_membership', {
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
groupId: integer('group_id').notNull().references(() => productGroupInfo.id),
|
|
||||||
addedAt: integer('added_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
pk: unique('product_group_membership_pk').on(t.productId, t.groupId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const homeBanners = sqliteTable('home_banners', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
imageUrl: text('image_url').notNull(),
|
|
||||||
description: text('description'),
|
|
||||||
productIds: text('product_ids'),
|
|
||||||
redirectUrl: text('redirect_url'),
|
|
||||||
serialNum: integer('serial_num'),
|
|
||||||
isActive: integer('is_active', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
lastUpdated: integer('last_updated', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productReviews = sqliteTable('product_reviews', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
reviewBody: text('review_body').notNull(),
|
|
||||||
imageUrls: text('image_urls').default('[]'),
|
|
||||||
reviewTime: integer('review_time', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
ratings: real('ratings').notNull(),
|
|
||||||
adminResponse: text('admin_response'),
|
|
||||||
adminResponseImages: text('admin_response_images').default('[]'),
|
|
||||||
}, (t) => ({
|
|
||||||
ratingCheck: check('rating_check', sql`${t.ratings} >= 1 AND ${t.ratings} <= 5`),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const uploadStatusEnum = sqliteEnum('upload_status', ['pending', 'claimed'])
|
|
||||||
|
|
||||||
export const uploadUrlStatus = sqliteTable('upload_url_status', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
key: text('key').notNull(),
|
|
||||||
status: uploadStatusEnum('status').notNull().default('pending'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productTagInfo = sqliteTable('product_tag_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
tagName: text('tag_name').notNull().unique(),
|
|
||||||
tagDescription: text('tag_description'),
|
|
||||||
imageUrl: text('image_url'),
|
|
||||||
isDashboardTag: integer('is_dashboard_tag', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
relatedStores: text('related_stores').default('[]'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productTags = sqliteTable('product_tags', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
tagId: integer('tag_id').notNull().references(() => productTagInfo.id),
|
|
||||||
assignedAt: integer('assigned_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_product_tag: unique('unique_product_tag').on(t.productId, t.tagId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const deliverySlotInfo = sqliteTable('delivery_slot_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
deliveryTime: integer('delivery_time', { mode: 'timestamp' }).notNull(),
|
|
||||||
freezeTime: integer('freeze_time', { mode: 'timestamp' }).notNull(),
|
|
||||||
isActive: integer('is_active', { mode: 'boolean' }).notNull().default(true),
|
|
||||||
isFlash: integer('is_flash', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isCapacityFull: integer('is_capacity_full', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
deliverySequence: text('delivery_sequence').default('{}'),
|
|
||||||
groupIds: text('group_ids').default('[]'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const vendorSnippets = sqliteTable('vendor_snippets', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
snippetCode: text('snippet_code').notNull().unique(),
|
|
||||||
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
|
||||||
isPermanent: integer('is_permanent', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
productIds: text('product_ids').notNull(),
|
|
||||||
validTill: integer('valid_till', { mode: 'timestamp' }),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productSlots = sqliteTable('product_slots', {
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
slotId: integer('slot_id').notNull().references(() => deliverySlotInfo.id),
|
|
||||||
}, (t) => ({
|
|
||||||
pk: unique('product_slot_pk').on(t.productId, t.slotId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const specialDeals = sqliteTable('special_deals', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: text('quantity').notNull(),
|
|
||||||
price: text('price').notNull(),
|
|
||||||
validTill: integer('valid_till', { mode: 'timestamp' }).notNull(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const paymentInfoTable = sqliteTable('payment_info', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
status: text('status').notNull(),
|
|
||||||
gateway: text('gateway').notNull(),
|
|
||||||
orderId: text('order_id'),
|
|
||||||
token: text('token'),
|
|
||||||
merchantOrderId: text('merchant_order_id').notNull().unique(),
|
|
||||||
payload: text('payload'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const orders = sqliteTable('orders', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
addressId: integer('address_id').notNull().references(() => addresses.id),
|
|
||||||
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
|
||||||
isCod: integer('is_cod', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isOnlinePayment: integer('is_online_payment', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
paymentInfoId: integer('payment_info_id').references(() => paymentInfoTable.id),
|
|
||||||
totalAmount: text('total_amount').notNull(),
|
|
||||||
deliveryCharge: text('delivery_charge').notNull().default('0'),
|
|
||||||
readableId: integer('readable_id').notNull(),
|
|
||||||
adminNotes: text('admin_notes'),
|
|
||||||
userNotes: text('user_notes'),
|
|
||||||
orderGroupId: text('order_group_id'),
|
|
||||||
orderGroupProportion: text('order_group_proportion'),
|
|
||||||
isFlashDelivery: integer('is_flash_delivery', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const orderItems = sqliteTable('order_items', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: text('quantity').notNull(),
|
|
||||||
price: text('price').notNull(),
|
|
||||||
discountedPrice: text('discounted_price'),
|
|
||||||
is_packaged: integer('is_packaged', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
is_package_verified: integer('is_package_verified', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const paymentStatusEnum = sqliteEnum('payment_status', [
|
|
||||||
'pending',
|
|
||||||
'success',
|
|
||||||
'cod',
|
|
||||||
'failed',
|
|
||||||
])
|
|
||||||
|
|
||||||
export const orderStatus = sqliteTable('order_status', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
orderTime: integer('order_time', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
isPackaged: integer('is_packaged', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isDelivered: integer('is_delivered', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isCancelled: integer('is_cancelled', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
cancelReason: text('cancel_reason'),
|
|
||||||
isCancelledByAdmin: integer('is_cancelled_by_admin', { mode: 'boolean' }),
|
|
||||||
paymentStatus: paymentStatusEnum('payment_state').notNull().default('pending'),
|
|
||||||
cancellationUserNotes: text('cancellation_user_notes'),
|
|
||||||
cancellationAdminNotes: text('cancellation_admin_notes'),
|
|
||||||
cancellationReviewed: integer('cancellation_reviewed', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
cancellationReviewedAt: integer('cancellation_reviewed_at', { mode: 'timestamp' }),
|
|
||||||
refundCouponId: integer('refund_coupon_id').references(() => coupons.id),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const payments = sqliteTable('payments', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
status: text('status').notNull(),
|
|
||||||
gateway: text('gateway').notNull(),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
token: text('token'),
|
|
||||||
merchantOrderId: text('merchant_order_id').notNull().unique(),
|
|
||||||
payload: text('payload'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const refunds = sqliteTable('refunds', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
orderId: integer('order_id').notNull().references(() => orders.id),
|
|
||||||
refundAmount: text('refund_amount'),
|
|
||||||
refundStatus: text('refund_status').default('none'),
|
|
||||||
merchantRefundId: text('merchant_refund_id'),
|
|
||||||
refundProcessedAt: integer('refund_processed_at', { mode: 'timestamp' }),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const keyValStore = sqliteTable('key_val_store', {
|
|
||||||
key: text('key').primaryKey(),
|
|
||||||
value: text('value'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const notifications = sqliteTable('notifications', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
title: text('title').notNull(),
|
|
||||||
body: text('body').notNull(),
|
|
||||||
type: text('type'),
|
|
||||||
isRead: integer('is_read', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const productCategories = sqliteTable('product_categories', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
name: text('name').notNull(),
|
|
||||||
description: text('description'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const cartItems = sqliteTable('cart_items', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
quantity: text('quantity').notNull(),
|
|
||||||
addedAt: integer('added_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_user_product: unique('unique_user_product').on(t.userId, t.productId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const complaints = sqliteTable('complaints', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
complaintBody: text('complaint_body').notNull(),
|
|
||||||
images: text('images'),
|
|
||||||
response: text('response'),
|
|
||||||
isResolved: integer('is_resolved', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const coupons = sqliteTable('coupons', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
couponCode: text('coupon_code').notNull().unique('unique_coupon_code'),
|
|
||||||
isUserBased: integer('is_user_based', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
discountPercent: text('discount_percent'),
|
|
||||||
flatDiscount: text('flat_discount'),
|
|
||||||
minOrder: text('min_order'),
|
|
||||||
productIds: text('product_ids'),
|
|
||||||
createdBy: integer('created_by').references(() => staffUsers.id),
|
|
||||||
maxValue: text('max_value'),
|
|
||||||
isApplyForAll: integer('is_apply_for_all', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
validTill: integer('valid_till', { mode: 'timestamp' }),
|
|
||||||
maxLimitForUser: integer('max_limit_for_user'),
|
|
||||||
isInvalidated: integer('is_invalidated', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
exclusiveApply: integer('exclusive_apply', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const couponUsage = sqliteTable('coupon_usage', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
orderItemId: integer('order_item_id').references(() => orderItems.id),
|
|
||||||
usedAt: integer('used_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const couponApplicableUsers = sqliteTable('coupon_applicable_users', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_coupon_user: unique('unique_coupon_user').on(t.couponId, t.userId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const couponApplicableProducts = sqliteTable('coupon_applicable_products', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
|
||||||
productId: integer('product_id').notNull().references(() => productInfo.id),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_coupon_product: unique('unique_coupon_product').on(t.couponId, t.productId),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const userIncidents = sqliteTable('user_incidents', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
orderId: integer('order_id').references(() => orders.id),
|
|
||||||
dateAdded: integer('date_added', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
adminComment: text('admin_comment'),
|
|
||||||
addedBy: integer('added_by').references(() => staffUsers.id),
|
|
||||||
negativityScore: integer('negativity_score'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const reservedCoupons = sqliteTable('reserved_coupons', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
secretCode: text('secret_code').notNull().unique(),
|
|
||||||
couponCode: text('coupon_code').notNull(),
|
|
||||||
discountPercent: text('discount_percent'),
|
|
||||||
flatDiscount: text('flat_discount'),
|
|
||||||
minOrder: text('min_order'),
|
|
||||||
productIds: text('product_ids'),
|
|
||||||
maxValue: text('max_value'),
|
|
||||||
validTill: integer('valid_till', { mode: 'timestamp' }),
|
|
||||||
maxLimitForUser: integer('max_limit_for_user'),
|
|
||||||
exclusiveApply: integer('exclusive_apply', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
isRedeemed: integer('is_redeemed', { mode: 'boolean' }).notNull().default(false),
|
|
||||||
redeemedBy: integer('redeemed_by').references(() => users.id),
|
|
||||||
redeemedAt: integer('redeemed_at', { mode: 'timestamp' }),
|
|
||||||
createdBy: integer('created_by').notNull().references(() => staffUsers.id),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
}, (t) => ({
|
|
||||||
unq_secret_code: unique('unique_secret_code').on(t.secretCode),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const notifCreds = sqliteTable('notif_creds', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
token: text('token').notNull().unique(),
|
|
||||||
addedAt: integer('added_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
userId: integer('user_id').notNull().references(() => users.id),
|
|
||||||
lastVerified: integer('last_verified', { mode: 'timestamp' }),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const unloggedUserTokens = sqliteTable('unlogged_user_tokens', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
token: text('token').notNull().unique(),
|
|
||||||
addedAt: integer('added_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
lastVerified: integer('last_verified', { mode: 'timestamp' }),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const userNotifications = sqliteTable('user_notifications', {
|
|
||||||
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
||||||
title: text('title').notNull(),
|
|
||||||
imageUrl: text('image_url'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(epochSeconds),
|
|
||||||
body: text('body').notNull(),
|
|
||||||
applicableUsers: text('applicable_users'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const uploadUrlStatusRelations = relations(uploadUrlStatus, ({}) => ({}))
|
|
||||||
|
|
||||||
export const userCredsRelations = relations(userCreds, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userCreds.userId], references: [users.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffUsersRelations = relations(staffUsers, ({ one, many }) => ({
|
|
||||||
role: one(staffRoles, { fields: [staffUsers.staffRoleId], references: [staffRoles.id] }),
|
|
||||||
coupons: many(coupons),
|
|
||||||
stores: many(storeInfo),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const addressesRelations = relations(addresses, ({ one, many }) => ({
|
|
||||||
user: one(users, { fields: [addresses.userId], references: [users.id] }),
|
|
||||||
orders: many(orders),
|
|
||||||
zone: one(addressZones, { fields: [addresses.zoneId], references: [addressZones.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const unitsRelations = relations(units, ({ many }) => ({
|
|
||||||
products: many(productInfo),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productInfoRelations = relations(productInfo, ({ one, many }) => ({
|
|
||||||
unit: one(units, { fields: [productInfo.unitId], references: [units.id] }),
|
|
||||||
store: one(storeInfo, { fields: [productInfo.storeId], references: [storeInfo.id] }),
|
|
||||||
productSlots: many(productSlots),
|
|
||||||
specialDeals: many(specialDeals),
|
|
||||||
orderItems: many(orderItems),
|
|
||||||
cartItems: many(cartItems),
|
|
||||||
tags: many(productTags),
|
|
||||||
applicableCoupons: many(couponApplicableProducts),
|
|
||||||
reviews: many(productReviews),
|
|
||||||
groups: many(productGroupMembership),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productTagInfoRelations = relations(productTagInfo, ({ many }) => ({
|
|
||||||
products: many(productTags),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productTagsRelations = relations(productTags, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productTags.productId], references: [productInfo.id] }),
|
|
||||||
tag: one(productTagInfo, { fields: [productTags.tagId], references: [productTagInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const deliverySlotInfoRelations = relations(deliverySlotInfo, ({ many }) => ({
|
|
||||||
productSlots: many(productSlots),
|
|
||||||
orders: many(orders),
|
|
||||||
vendorSnippets: many(vendorSnippets),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const vendorSnippetsRelations = relations(vendorSnippets, ({ one }) => ({
|
|
||||||
slot: one(deliverySlotInfo, { fields: [vendorSnippets.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productSlotsRelations = relations(productSlots, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productSlots.productId], references: [productInfo.id] }),
|
|
||||||
slot: one(deliverySlotInfo, { fields: [productSlots.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const specialDealsRelations = relations(specialDeals, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [specialDeals.productId], references: [productInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const ordersRelations = relations(orders, ({ one, many }) => ({
|
|
||||||
user: one(users, { fields: [orders.userId], references: [users.id] }),
|
|
||||||
address: one(addresses, { fields: [orders.addressId], references: [addresses.id] }),
|
|
||||||
slot: one(deliverySlotInfo, { fields: [orders.slotId], references: [deliverySlotInfo.id] }),
|
|
||||||
orderItems: many(orderItems),
|
|
||||||
payment: one(payments),
|
|
||||||
paymentInfo: one(paymentInfoTable, { fields: [orders.paymentInfoId], references: [paymentInfoTable.id] }),
|
|
||||||
orderStatus: many(orderStatus),
|
|
||||||
refunds: many(refunds),
|
|
||||||
couponUsages: many(couponUsage),
|
|
||||||
userIncidents: many(userIncidents),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const orderItemsRelations = relations(orderItems, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [orderItems.orderId], references: [orders.id] }),
|
|
||||||
product: one(productInfo, { fields: [orderItems.productId], references: [productInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const orderStatusRelations = relations(orderStatus, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [orderStatus.orderId], references: [orders.id] }),
|
|
||||||
user: one(users, { fields: [orderStatus.userId], references: [users.id] }),
|
|
||||||
refundCoupon: one(coupons, { fields: [orderStatus.refundCouponId], references: [coupons.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const paymentInfoRelations = relations(paymentInfoTable, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [paymentInfoTable.id], references: [orders.paymentInfoId] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const paymentsRelations = relations(payments, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [payments.orderId], references: [orders.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const refundsRelations = relations(refunds, ({ one }) => ({
|
|
||||||
order: one(orders, { fields: [refunds.orderId], references: [orders.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [notifications.userId], references: [users.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productCategoriesRelations = relations(productCategories, ({}) => ({}))
|
|
||||||
|
|
||||||
export const cartItemsRelations = relations(cartItems, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [cartItems.userId], references: [users.id] }),
|
|
||||||
product: one(productInfo, { fields: [cartItems.productId], references: [productInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const complaintsRelations = relations(complaints, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [complaints.userId], references: [users.id] }),
|
|
||||||
order: one(orders, { fields: [complaints.orderId], references: [orders.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const couponsRelations = relations(coupons, ({ one, many }) => ({
|
|
||||||
creator: one(staffUsers, { fields: [coupons.createdBy], references: [staffUsers.id] }),
|
|
||||||
usages: many(couponUsage),
|
|
||||||
applicableUsers: many(couponApplicableUsers),
|
|
||||||
applicableProducts: many(couponApplicableProducts),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const couponUsageRelations = relations(couponUsage, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [couponUsage.userId], references: [users.id] }),
|
|
||||||
coupon: one(coupons, { fields: [couponUsage.couponId], references: [coupons.id] }),
|
|
||||||
order: one(orders, { fields: [couponUsage.orderId], references: [orders.id] }),
|
|
||||||
orderItem: one(orderItems, { fields: [couponUsage.orderItemId], references: [orderItems.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const userDetailsRelations = relations(userDetails, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userDetails.userId], references: [users.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const notifCredsRelations = relations(notifCreds, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [notifCreds.userId], references: [users.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const userNotificationsRelations = relations(userNotifications, ({}) => ({}))
|
|
||||||
|
|
||||||
export const storeInfoRelations = relations(storeInfo, ({ one, many }) => ({
|
|
||||||
owner: one(staffUsers, { fields: [storeInfo.owner], references: [staffUsers.id] }),
|
|
||||||
products: many(productInfo),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const couponApplicableUsersRelations = relations(couponApplicableUsers, ({ one }) => ({
|
|
||||||
coupon: one(coupons, { fields: [couponApplicableUsers.couponId], references: [coupons.id] }),
|
|
||||||
user: one(users, { fields: [couponApplicableUsers.userId], references: [users.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const couponApplicableProductsRelations = relations(couponApplicableProducts, ({ one }) => ({
|
|
||||||
coupon: one(coupons, { fields: [couponApplicableProducts.couponId], references: [coupons.id] }),
|
|
||||||
product: one(productInfo, { fields: [couponApplicableProducts.productId], references: [productInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const reservedCouponsRelations = relations(reservedCoupons, ({ one }) => ({
|
|
||||||
redeemedUser: one(users, { fields: [reservedCoupons.redeemedBy], references: [users.id] }),
|
|
||||||
creator: one(staffUsers, { fields: [reservedCoupons.createdBy], references: [staffUsers.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productReviewsRelations = relations(productReviews, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [productReviews.userId], references: [users.id] }),
|
|
||||||
product: one(productInfo, { fields: [productReviews.productId], references: [productInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const addressZonesRelations = relations(addressZones, ({ many }) => ({
|
|
||||||
addresses: many(addresses),
|
|
||||||
areas: many(addressAreas),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const addressAreasRelations = relations(addressAreas, ({ one }) => ({
|
|
||||||
zone: one(addressZones, { fields: [addressAreas.zoneId], references: [addressZones.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productGroupInfoRelations = relations(productGroupInfo, ({ many }) => ({
|
|
||||||
memberships: many(productGroupMembership),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productGroupMembershipRelations = relations(productGroupMembership, ({ one }) => ({
|
|
||||||
product: one(productInfo, { fields: [productGroupMembership.productId], references: [productInfo.id] }),
|
|
||||||
group: one(productGroupInfo, { fields: [productGroupMembership.groupId], references: [productGroupInfo.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const homeBannersRelations = relations(homeBanners, ({}) => ({}))
|
|
||||||
|
|
||||||
export const staffRolesRelations = relations(staffRoles, ({ many }) => ({
|
|
||||||
staffUsers: many(staffUsers),
|
|
||||||
rolePermissions: many(staffRolePermissions),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffPermissionsRelations = relations(staffPermissions, ({ many }) => ({
|
|
||||||
rolePermissions: many(staffRolePermissions),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const staffRolePermissionsRelations = relations(staffRolePermissions, ({ one }) => ({
|
|
||||||
role: one(staffRoles, { fields: [staffRolePermissions.staffRoleId], references: [staffRoles.id] }),
|
|
||||||
permission: one(staffPermissions, { fields: [staffRolePermissions.staffPermissionId], references: [staffPermissions.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const userIncidentsRelations = relations(userIncidents, ({ one }) => ({
|
|
||||||
user: one(users, { fields: [userIncidents.userId], references: [users.id] }),
|
|
||||||
order: one(orders, { fields: [userIncidents.orderId], references: [orders.id] }),
|
|
||||||
addedBy: one(staffUsers, { fields: [userIncidents.addedBy], references: [staffUsers.id] }),
|
|
||||||
}))
|
|
||||||
|
|
||||||
export const productAvailabilitySchedulesRelations = relations(
|
|
||||||
productAvailabilitySchedules,
|
|
||||||
({}) => ({})
|
|
||||||
)
|
|
||||||
|
|
||||||
export const usersRelations = relations(users, ({ many, one }) => ({
|
|
||||||
addresses: many(addresses),
|
|
||||||
orders: many(orders),
|
|
||||||
notifications: many(notifications),
|
|
||||||
cartItems: many(cartItems),
|
|
||||||
userCreds: one(userCreds),
|
|
||||||
coupons: many(coupons),
|
|
||||||
couponUsages: many(couponUsage),
|
|
||||||
applicableCoupons: many(couponApplicableUsers),
|
|
||||||
userDetails: one(userDetails),
|
|
||||||
notifCreds: many(notifCreds),
|
|
||||||
userIncidents: many(userIncidents),
|
|
||||||
}))
|
|
||||||
|
|
|
||||||
|
|
@ -1,138 +1,8 @@
|
||||||
import { db } from "@/src/db/db_index"
|
import { seed as seedPostgres } from '@db-helper-postgres/db/seed'
|
||||||
import { units, productInfo, deliverySlotInfo, productSlots, keyValStore, staffRoles, staffPermissions, staffRolePermissions } from "@/src/db/schema"
|
import { seed as seedSqlite } from '@db-helper-sqlite/db/seed'
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import { minOrderValue, deliveryCharge } from '@/src/lib/env-exporter'
|
|
||||||
import { CONST_KEYS } from '@/src/lib/const-keys'
|
|
||||||
|
|
||||||
export async function seed() {
|
const dialect = process.env.DB_DIALECT || DB_DIALECT_TYPE
|
||||||
console.log("Seeding database...");
|
|
||||||
|
|
||||||
// Seed units individually
|
const seedImpl = dialect === 'sqlite' ? seedSqlite : seedPostgres
|
||||||
const unitsToSeed = [
|
|
||||||
{ shortNotation: "Kg", fullName: "Kilogram" },
|
|
||||||
{ shortNotation: "L", fullName: "Litre" },
|
|
||||||
{ shortNotation: "Dz", fullName: "Dozen" },
|
|
||||||
{ shortNotation: "Pc", fullName: "Unit Piece" },
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const unit of unitsToSeed) {
|
export const seed = async () => seedImpl()
|
||||||
const existingUnit = await db.query.units.findFirst({
|
|
||||||
where: eq(units.shortNotation, unit.shortNotation),
|
|
||||||
});
|
|
||||||
if (!existingUnit) {
|
|
||||||
await db.insert(units).values(unit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seed staff roles individually
|
|
||||||
const rolesToSeed = ['super_admin', 'admin', 'marketer', 'delivery_staff'] as const;
|
|
||||||
|
|
||||||
for (const roleName of rolesToSeed) {
|
|
||||||
const existingRole = await db.query.staffRoles.findFirst({
|
|
||||||
where: eq(staffRoles.roleName, roleName),
|
|
||||||
});
|
|
||||||
if (!existingRole) {
|
|
||||||
await db.insert(staffRoles).values({ roleName });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seed staff permissions individually
|
|
||||||
const permissionsToSeed = ['crud_product', 'make_coupon', 'crud_staff_users'] as const;
|
|
||||||
|
|
||||||
for (const permissionName of permissionsToSeed) {
|
|
||||||
const existingPermission = await db.query.staffPermissions.findFirst({
|
|
||||||
where: eq(staffPermissions.permissionName, permissionName),
|
|
||||||
});
|
|
||||||
if (!existingPermission) {
|
|
||||||
await db.insert(staffPermissions).values({ permissionName });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seed role-permission assignments
|
|
||||||
await db.transaction(async (tx) => {
|
|
||||||
// Get role IDs
|
|
||||||
const superAdminRole = await tx.query.staffRoles.findFirst({ where: eq(staffRoles.roleName, 'super_admin') });
|
|
||||||
const adminRole = await tx.query.staffRoles.findFirst({ where: eq(staffRoles.roleName, 'admin') });
|
|
||||||
const marketerRole = await tx.query.staffRoles.findFirst({ where: eq(staffRoles.roleName, 'marketer') });
|
|
||||||
|
|
||||||
// Get permission IDs
|
|
||||||
const crudProductPerm = await tx.query.staffPermissions.findFirst({ where: eq(staffPermissions.permissionName, 'crud_product') });
|
|
||||||
const makeCouponPerm = await tx.query.staffPermissions.findFirst({ where: eq(staffPermissions.permissionName, 'make_coupon') });
|
|
||||||
const crudStaffUsersPerm = await tx.query.staffPermissions.findFirst({ where: eq(staffPermissions.permissionName, 'crud_staff_users') });
|
|
||||||
|
|
||||||
// Assign all permissions to super_admin
|
|
||||||
[crudProductPerm, makeCouponPerm, crudStaffUsersPerm].forEach(async (perm) => {
|
|
||||||
if (superAdminRole && perm) {
|
|
||||||
const existingSuperAdminPerm = await tx.query.staffRolePermissions.findFirst({
|
|
||||||
where: eq(staffRolePermissions.staffRoleId, superAdminRole.id) && eq(staffRolePermissions.staffPermissionId, perm.id),
|
|
||||||
});
|
|
||||||
if (!existingSuperAdminPerm) {
|
|
||||||
await tx.insert(staffRolePermissions).values({
|
|
||||||
staffRoleId: superAdminRole.id,
|
|
||||||
staffPermissionId: perm.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assign all permissions to admin
|
|
||||||
[crudProductPerm, makeCouponPerm].forEach(async (perm) => {
|
|
||||||
if (adminRole && perm) {
|
|
||||||
const existingAdminPerm = await tx.query.staffRolePermissions.findFirst({
|
|
||||||
where: eq(staffRolePermissions.staffRoleId, adminRole.id) && eq(staffRolePermissions.staffPermissionId, perm.id),
|
|
||||||
});
|
|
||||||
if (!existingAdminPerm) {
|
|
||||||
await tx.insert(staffRolePermissions).values({
|
|
||||||
staffRoleId: adminRole.id,
|
|
||||||
staffPermissionId: perm.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assign make_coupon to marketer
|
|
||||||
if (marketerRole && makeCouponPerm) {
|
|
||||||
const existingMarketerCoupon = await tx.query.staffRolePermissions.findFirst({
|
|
||||||
where: eq(staffRolePermissions.staffRoleId, marketerRole.id) && eq(staffRolePermissions.staffPermissionId, makeCouponPerm.id),
|
|
||||||
});
|
|
||||||
if (!existingMarketerCoupon) {
|
|
||||||
await tx.insert(staffRolePermissions).values({
|
|
||||||
staffRoleId: marketerRole.id,
|
|
||||||
staffPermissionId: makeCouponPerm.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Seed key-val store constants using CONST_KEYS
|
|
||||||
const constantsToSeed = [
|
|
||||||
{ key: CONST_KEYS.readableOrderId, value: 0 },
|
|
||||||
{ key: CONST_KEYS.minRegularOrderValue, value: minOrderValue },
|
|
||||||
{ key: CONST_KEYS.freeDeliveryThreshold, value: minOrderValue },
|
|
||||||
{ key: CONST_KEYS.deliveryCharge, value: deliveryCharge },
|
|
||||||
{ key: CONST_KEYS.flashFreeDeliveryThreshold, value: 500 },
|
|
||||||
{ key: CONST_KEYS.flashDeliveryCharge, value: 69 },
|
|
||||||
{ key: CONST_KEYS.popularItems, value: [] },
|
|
||||||
{ key: CONST_KEYS.allItemsOrder, value: [] },
|
|
||||||
{ key: CONST_KEYS.versionNum, value: '1.1.0' },
|
|
||||||
{ key: CONST_KEYS.playStoreUrl, value: 'https://play.google.com/store/apps/details?id=in.freshyo.app' },
|
|
||||||
{ key: CONST_KEYS.appStoreUrl, value: 'https://apps.apple.com/in/app/freshyo/id6756889077' },
|
|
||||||
{ key: CONST_KEYS.isFlashDeliveryEnabled, value: false },
|
|
||||||
{ key: CONST_KEYS.supportMobile, value: '8688182552' },
|
|
||||||
{ key: CONST_KEYS.supportEmail, value: 'qushammohd@gmail.com' },
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const constant of constantsToSeed) {
|
|
||||||
const existing = await db.query.keyValStore.findFirst({
|
|
||||||
where: eq(keyValStore.key, constant.key),
|
|
||||||
});
|
|
||||||
if (!existing) {
|
|
||||||
await db.insert(keyValStore).values({
|
|
||||||
key: constant.key,
|
|
||||||
value: constant.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Seeding completed.");
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1 @@
|
||||||
export const parseJsonValue = <T>(value: unknown, fallback: T): T => {
|
export * from '@/db-helper-sqlite/db/sqlite-casts'
|
||||||
if (value === null || value === undefined) return fallback
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
try {
|
|
||||||
return JSON.parse(value) as T
|
|
||||||
} catch {
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value as T
|
|
||||||
}
|
|
||||||
|
|
||||||
export const parseNumberArray = (value: unknown): number[] => {
|
|
||||||
const parsed = parseJsonValue<unknown[]>(value, [])
|
|
||||||
return parsed
|
|
||||||
.map((item) => Number(item))
|
|
||||||
.filter((item) => !Number.isNaN(item))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toJsonString = (value: unknown, fallback: string): string => {
|
|
||||||
if (value === null || value === undefined) return fallback
|
|
||||||
if (typeof value === 'string') return value
|
|
||||||
return JSON.stringify(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toEpochSeconds = (value: Date | number): number => {
|
|
||||||
if (typeof value === 'number') return value
|
|
||||||
return Math.floor(value.getTime() / 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fromEpochSeconds = (value: number | null | undefined): Date | null => {
|
|
||||||
if (value === null || value === undefined) return null
|
|
||||||
return new Date(value * 1000)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,58 @@
|
||||||
import type { InferSelectModel } from "drizzle-orm";
|
|
||||||
import type {
|
import type {
|
||||||
users,
|
User as PostgresUser,
|
||||||
addresses,
|
Address as PostgresAddress,
|
||||||
units,
|
Unit as PostgresUnit,
|
||||||
productInfo,
|
ProductInfo as PostgresProductInfo,
|
||||||
deliverySlotInfo,
|
DeliverySlotInfo as PostgresDeliverySlotInfo,
|
||||||
productSlots,
|
ProductSlot as PostgresProductSlot,
|
||||||
specialDeals,
|
SpecialDeal as PostgresSpecialDeal,
|
||||||
orders,
|
Order as PostgresOrder,
|
||||||
orderItems,
|
OrderItem as PostgresOrderItem,
|
||||||
payments,
|
Payment as PostgresPayment,
|
||||||
notifications,
|
Notification as PostgresNotification,
|
||||||
productCategories,
|
ProductCategory as PostgresProductCategory,
|
||||||
cartItems,
|
CartItem as PostgresCartItem,
|
||||||
coupons,
|
Coupon as PostgresCoupon,
|
||||||
} from "@/src/db/schema";
|
ProductWithUnit as PostgresProductWithUnit,
|
||||||
|
OrderWithItems as PostgresOrderWithItems,
|
||||||
|
CartItemWithProduct as PostgresCartItemWithProduct,
|
||||||
|
} from '@db-helper-postgres/db/types'
|
||||||
|
import type {
|
||||||
|
User as SqliteUser,
|
||||||
|
Address as SqliteAddress,
|
||||||
|
Unit as SqliteUnit,
|
||||||
|
ProductInfo as SqliteProductInfo,
|
||||||
|
DeliverySlotInfo as SqliteDeliverySlotInfo,
|
||||||
|
ProductSlot as SqliteProductSlot,
|
||||||
|
SpecialDeal as SqliteSpecialDeal,
|
||||||
|
Order as SqliteOrder,
|
||||||
|
OrderItem as SqliteOrderItem,
|
||||||
|
Payment as SqlitePayment,
|
||||||
|
Notification as SqliteNotification,
|
||||||
|
ProductCategory as SqliteProductCategory,
|
||||||
|
CartItem as SqliteCartItem,
|
||||||
|
Coupon as SqliteCoupon,
|
||||||
|
ProductWithUnit as SqliteProductWithUnit,
|
||||||
|
OrderWithItems as SqliteOrderWithItems,
|
||||||
|
CartItemWithProduct as SqliteCartItemWithProduct,
|
||||||
|
} from '@db-helper-sqlite/db/types'
|
||||||
|
|
||||||
export type User = InferSelectModel<typeof users>;
|
type UseSqlite = typeof DB_DIALECT_TYPE extends 'sqlite' ? true : false
|
||||||
export type Address = InferSelectModel<typeof addresses>;
|
|
||||||
export type Unit = InferSelectModel<typeof units>;
|
|
||||||
export type ProductInfo = InferSelectModel<typeof productInfo>;
|
|
||||||
export type DeliverySlotInfo = InferSelectModel<typeof deliverySlotInfo>;
|
|
||||||
export type ProductSlot = InferSelectModel<typeof productSlots>;
|
|
||||||
export type SpecialDeal = InferSelectModel<typeof specialDeals>;
|
|
||||||
export type Order = InferSelectModel<typeof orders>;
|
|
||||||
export type OrderItem = InferSelectModel<typeof orderItems>;
|
|
||||||
export type Payment = InferSelectModel<typeof payments>;
|
|
||||||
export type Notification = InferSelectModel<typeof notifications>;
|
|
||||||
export type ProductCategory = InferSelectModel<typeof productCategories>;
|
|
||||||
export type CartItem = InferSelectModel<typeof cartItems>;
|
|
||||||
export type Coupon = InferSelectModel<typeof coupons>;
|
|
||||||
|
|
||||||
// Combined types
|
export type User = UseSqlite extends true ? SqliteUser : PostgresUser
|
||||||
export type ProductWithUnit = ProductInfo & {
|
export type Address = UseSqlite extends true ? SqliteAddress : PostgresAddress
|
||||||
unit: Unit;
|
export type Unit = UseSqlite extends true ? SqliteUnit : PostgresUnit
|
||||||
};
|
export type ProductInfo = UseSqlite extends true ? SqliteProductInfo : PostgresProductInfo
|
||||||
|
export type DeliverySlotInfo = UseSqlite extends true ? SqliteDeliverySlotInfo : PostgresDeliverySlotInfo
|
||||||
export type OrderWithItems = Order & {
|
export type ProductSlot = UseSqlite extends true ? SqliteProductSlot : PostgresProductSlot
|
||||||
items: (OrderItem & { product: ProductInfo })[];
|
export type SpecialDeal = UseSqlite extends true ? SqliteSpecialDeal : PostgresSpecialDeal
|
||||||
address: Address;
|
export type Order = UseSqlite extends true ? SqliteOrder : PostgresOrder
|
||||||
slot: DeliverySlotInfo;
|
export type OrderItem = UseSqlite extends true ? SqliteOrderItem : PostgresOrderItem
|
||||||
};
|
export type Payment = UseSqlite extends true ? SqlitePayment : PostgresPayment
|
||||||
|
export type Notification = UseSqlite extends true ? SqliteNotification : PostgresNotification
|
||||||
export type CartItemWithProduct = CartItem & {
|
export type ProductCategory = UseSqlite extends true ? SqliteProductCategory : PostgresProductCategory
|
||||||
product: ProductInfo;
|
export type CartItem = UseSqlite extends true ? SqliteCartItem : PostgresCartItem
|
||||||
};
|
export type Coupon = UseSqlite extends true ? SqliteCoupon : PostgresCoupon
|
||||||
|
export type ProductWithUnit = UseSqlite extends true ? SqliteProductWithUnit : PostgresProductWithUnit
|
||||||
|
export type OrderWithItems = UseSqlite extends true ? SqliteOrderWithItems : PostgresOrderWithItems
|
||||||
|
export type CartItemWithProduct = UseSqlite extends true ? SqliteCartItemWithProduct : PostgresCartItemWithProduct
|
||||||
|
|
|
||||||
14
apps/backend/src/db/upload-url.ts
Normal file
14
apps/backend/src/db/upload-url.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { claimUploadUrlStatus as claimUploadUrlStatusPostgres, createUploadUrlStatus as createUploadUrlStatusPostgres } from '@db-helper-postgres/lib/upload-url'
|
||||||
|
import { claimUploadUrlStatus as claimUploadUrlStatusSqlite, createUploadUrlStatus as createUploadUrlStatusSqlite } from '@db-helper-sqlite/lib/upload-url'
|
||||||
|
|
||||||
|
const dialect = process.env.DB_DIALECT || DB_DIALECT_TYPE
|
||||||
|
|
||||||
|
const createUploadUrlStatus = dialect === 'sqlite'
|
||||||
|
? createUploadUrlStatusSqlite
|
||||||
|
: createUploadUrlStatusPostgres
|
||||||
|
|
||||||
|
const claimUploadUrlStatus = dialect === 'sqlite'
|
||||||
|
? claimUploadUrlStatusSqlite
|
||||||
|
: claimUploadUrlStatusPostgres
|
||||||
|
|
||||||
|
export { claimUploadUrlStatus, createUploadUrlStatus }
|
||||||
|
|
@ -1,56 +1,54 @@
|
||||||
import { eq } from "drizzle-orm";
|
import { deleteImageUtil, getOriginalUrlFromSignedUrl } from '@/src/lib/s3-client'
|
||||||
import { db } from "@/src/db/db_index"
|
import { assetsDomain, s3Url } from '@/src/lib/env-exporter'
|
||||||
import { deleteImageUtil, getOriginalUrlFromSignedUrl } from "@/src/lib/s3-client"
|
|
||||||
import { assetsDomain, s3Url } from "@/src/lib/env-exporter"
|
|
||||||
|
|
||||||
function extractS3Key(url: string): string | null {
|
function extractS3Key(url: string): string | null {
|
||||||
try {
|
try {
|
||||||
// Check if this is a signed URL first and get the original if it is
|
// Check if this is a signed URL first and get the original if it is
|
||||||
const originalUrl = getOriginalUrlFromSignedUrl(url) || url;
|
const originalUrl = getOriginalUrlFromSignedUrl(url) || url
|
||||||
|
|
||||||
// Find the index of '.com/' in the URL
|
// Find the index of '.com/' in the URL
|
||||||
// const comIndex = originalUrl.indexOf(".com/");
|
// const comIndex = originalUrl.indexOf(".com/");
|
||||||
const baseUrlIndex = originalUrl.indexOf(s3Url);
|
const baseUrlIndex = originalUrl.indexOf(s3Url)
|
||||||
|
|
||||||
// If '.com/' is found, return everything after it
|
// If '.com/' is found, return everything after it
|
||||||
if (baseUrlIndex !== -1) {
|
if (baseUrlIndex !== -1) {
|
||||||
return originalUrl.substring(baseUrlIndex + s3Url.length); // +5 to skip '.com/'
|
return originalUrl.substring(baseUrlIndex + s3Url.length) // +5 to skip '.com/'
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error extracting key from URL:", error);
|
console.error('Error extracting key from URL:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return null if the pattern isn't found or there was an error
|
// Return null if the pattern isn't found or there was an error
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function deleteS3Image(imageUrl: string) {
|
export async function deleteS3Image(imageUrl: string) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let key:string | null = '';
|
let key: string | null = ''
|
||||||
|
|
||||||
if(imageUrl.includes(assetsDomain)) {
|
if (imageUrl.includes(assetsDomain)) {
|
||||||
key = imageUrl.replace(assetsDomain, '')
|
key = imageUrl.replace(assetsDomain, '')
|
||||||
}
|
}
|
||||||
else if(imageUrl.startsWith('http')){
|
else if (imageUrl.startsWith('http')) {
|
||||||
// First check if this is a signed URL and get the original if it is
|
// First check if this is a signed URL and get the original if it is
|
||||||
const originalUrl = getOriginalUrlFromSignedUrl(imageUrl) || imageUrl;
|
const originalUrl = getOriginalUrlFromSignedUrl(imageUrl) || imageUrl
|
||||||
|
|
||||||
key = extractS3Key(originalUrl || "");
|
key = extractS3Key(originalUrl || '')
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
key = imageUrl;
|
key = imageUrl
|
||||||
}
|
}
|
||||||
if (!key) {
|
if (!key) {
|
||||||
throw new Error("Invalid image URL format");
|
throw new Error('Invalid image URL format')
|
||||||
}
|
}
|
||||||
const deleteS3 = await deleteImageUtil({keys: [key] });
|
const deleteS3 = await deleteImageUtil({ keys: [key] })
|
||||||
if (!deleteS3) {
|
if (!deleteS3) {
|
||||||
throw new Error("Failed to delete image from S3");
|
throw new Error('Failed to delete image from S3')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error deleting image from S3:", error);
|
console.error('Error deleting image from S3:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { db } from "@/src/db/db_index"
|
import { sendPushNotificationsMany } from '@/src/lib/expo-service'
|
||||||
import { sendPushNotificationsMany } from "@/src/lib/expo-service"
|
|
||||||
// import { usersTable, notifCredsTable, notificationTable } from "@/src/db/schema";
|
// import { usersTable, notifCredsTable, notificationTable } from "@/src/db/schema";
|
||||||
import { eq, inArray } from "drizzle-orm";
|
|
||||||
|
|
||||||
// Core notification dispatch methods (renamed for clarity)
|
// Core notification dispatch methods (renamed for clarity)
|
||||||
export async function dispatchBulkNotification({
|
export async function dispatchBulkNotification({
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import { db } from "@/src/db/db_index"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants for role names to avoid hardcoding and typos
|
* Constants for role names to avoid hardcoding and typos
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,7 @@ import { DeleteObjectCommand, DeleteObjectsCommand, PutObjectCommand, S3Client,
|
||||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
|
||||||
import signedUrlCache from "@/src/lib/signed-url-cache"
|
import signedUrlCache from "@/src/lib/signed-url-cache"
|
||||||
import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName, assetsDomain } from "@/src/lib/env-exporter"
|
import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName, assetsDomain } from "@/src/lib/env-exporter"
|
||||||
import { db } from "@/src/db/db_index"; // Adjust path if needed
|
import { claimUploadUrlStatus, createUploadUrlStatus } from '@/src/db/upload-url'
|
||||||
import { uploadUrlStatus } from "@/src/db/schema"
|
|
||||||
import { and, eq } from 'drizzle-orm';
|
|
||||||
|
|
||||||
const s3Client = new S3Client({
|
const s3Client = new S3Client({
|
||||||
region: s3Region,
|
region: s3Region,
|
||||||
|
|
@ -161,10 +159,7 @@ export async function generateSignedUrlsFromS3Urls(s3Urls: (string|null)[], expi
|
||||||
export async function generateUploadUrl(key: string, mimeType: string, expiresIn: number = 180): Promise<string> {
|
export async function generateUploadUrl(key: string, mimeType: string, expiresIn: number = 180): Promise<string> {
|
||||||
try {
|
try {
|
||||||
// Insert record into upload_url_status
|
// Insert record into upload_url_status
|
||||||
await db.insert(uploadUrlStatus).values({
|
await createUploadUrlStatus(key)
|
||||||
key: key,
|
|
||||||
status: 'pending',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate signed upload URL
|
// Generate signed upload URL
|
||||||
const command = new PutObjectCommand({
|
const command = new PutObjectCommand({
|
||||||
|
|
@ -207,16 +202,7 @@ export async function claimUploadUrl(url: string): Promise<void> {
|
||||||
semiKey = extractKeyFromPresignedUrl(url);
|
semiKey = extractKeyFromPresignedUrl(url);
|
||||||
else
|
else
|
||||||
semiKey = url
|
semiKey = url
|
||||||
// Update status to 'claimed' if currently 'pending'
|
await claimUploadUrlStatus(semiKey)
|
||||||
const result = await db
|
|
||||||
.update(uploadUrlStatus)
|
|
||||||
.set({ status: 'claimed' })
|
|
||||||
.where(and(eq(uploadUrlStatus.key, semiKey), eq(uploadUrlStatus.status, 'pending')))
|
|
||||||
.returning();
|
|
||||||
|
|
||||||
if (result.length === 0) {
|
|
||||||
throw new Error('Upload URL not found or already claimed');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error claiming upload URL:', error);
|
console.error('Error claiming upload URL:', error);
|
||||||
throw new Error('Failed to claim upload URL');
|
throw new Error('Failed to claim upload URL');
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,60 @@
|
||||||
export type { IBannerDbService, Banner, NewBanner } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
export type { IBannerDbService, Banner, NewBanner } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
||||||
// export { bannerDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/banner-queries'
|
|
||||||
export { bannerDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/banner-queries'
|
|
||||||
|
|
||||||
export type { IComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
export type { IComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
||||||
// export { complaintDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/complaint-queries'
|
|
||||||
export { complaintDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/complaint-queries'
|
|
||||||
|
|
||||||
export type { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
export type { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||||
// export { constantDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/constant-queries'
|
|
||||||
export { constantDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/constant-queries'
|
|
||||||
|
|
||||||
export type { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
export type { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
||||||
// export { couponDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/coupon-queries'
|
|
||||||
export { couponDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/coupon-queries'
|
|
||||||
|
|
||||||
export type { IOrderDbService, Order, OrderItem, OrderStatus, OrderWithRelations, OrderWithStatus, OrderWithCouponUsages } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
export type { IOrderDbService, Order, OrderItem, OrderStatus, OrderWithRelations, OrderWithStatus, OrderWithCouponUsages } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
||||||
// export { orderDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/order-queries'
|
|
||||||
export { orderDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/order-queries'
|
|
||||||
|
|
||||||
export type { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
export type { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
||||||
// export { productDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/product-queries'
|
|
||||||
export { productDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/product-queries'
|
|
||||||
|
|
||||||
export type { IRefundDbService, Refund, NewRefund } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
export type { IRefundDbService, Refund, NewRefund } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
||||||
// export { refundDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/refund-queries'
|
|
||||||
export { refundDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/refund-queries'
|
|
||||||
|
|
||||||
export type { IScheduleDbService, Schedule, NewSchedule } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
export type { IScheduleDbService, Schedule, NewSchedule } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
||||||
// export { scheduleDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/schedule-queries'
|
|
||||||
export { scheduleDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/schedule-queries'
|
|
||||||
|
|
||||||
export type { ISlotDbService, Slot, NewSlot, ProductSlot, NewProductSlot, SlotWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
export type { ISlotDbService, Slot, NewSlot, ProductSlot, NewProductSlot, SlotWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
||||||
// export { slotDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/slot-queries'
|
|
||||||
export { slotDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/slot-queries'
|
|
||||||
|
|
||||||
export type { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole, StaffUserWithRole } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
export type { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole, StaffUserWithRole } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
||||||
// export { staffUserDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/staff-user-queries'
|
|
||||||
export { staffUserDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/staff-user-queries'
|
|
||||||
|
|
||||||
export type { IStoreDbService, Store, NewStore } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
export type { IStoreDbService, Store, NewStore } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
||||||
// export { storeDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/store-queries'
|
|
||||||
export { storeDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/store-queries'
|
|
||||||
|
|
||||||
export type { ITagDbService, Tag, NewTag } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
export type { ITagDbService, Tag, NewTag } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
||||||
// export { tagDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/tag-queries'
|
|
||||||
export { tagDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/tag-queries'
|
|
||||||
|
|
||||||
export type { IUserDbService, User, NewUser, UserDetail } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
export type { IUserDbService, User, NewUser, UserDetail } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
||||||
// export { userDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/user-queries'
|
|
||||||
export { userDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/user-queries'
|
|
||||||
|
|
||||||
export type { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
export type { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
||||||
// export { vendorSnippetDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/postgres/vendor-snippets-queries'
|
|
||||||
export { vendorSnippetDbService } from '@/src/trpc/apis/admin-apis/dataAccessors/sqlite/vendor-snippets-queries'
|
import { bannerDbService as sqliteBannerDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/banner-queries'
|
||||||
|
import { bannerDbService as postgresBannerDbService } from '@db-helper-postgres/dataAccessors/admin-apis/banner-queries'
|
||||||
|
import { complaintDbService as sqliteComplaintDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/complaint-queries'
|
||||||
|
import { complaintDbService as postgresComplaintDbService } from '@db-helper-postgres/dataAccessors/admin-apis/complaint-queries'
|
||||||
|
import { constantDbService as sqliteConstantDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/constant-queries'
|
||||||
|
import { constantDbService as postgresConstantDbService } from '@db-helper-postgres/dataAccessors/admin-apis/constant-queries'
|
||||||
|
import { couponDbService as sqliteCouponDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/coupon-queries'
|
||||||
|
import { couponDbService as postgresCouponDbService } from '@db-helper-postgres/dataAccessors/admin-apis/coupon-queries'
|
||||||
|
import { orderDbService as sqliteOrderDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/order-queries'
|
||||||
|
import { orderDbService as postgresOrderDbService } from '@db-helper-postgres/dataAccessors/admin-apis/order-queries'
|
||||||
|
import { productDbService as sqliteProductDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/product-queries'
|
||||||
|
import { productDbService as postgresProductDbService } from '@db-helper-postgres/dataAccessors/admin-apis/product-queries'
|
||||||
|
import { refundDbService as sqliteRefundDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/refund-queries'
|
||||||
|
import { refundDbService as postgresRefundDbService } from '@db-helper-postgres/dataAccessors/admin-apis/refund-queries'
|
||||||
|
import { scheduleDbService as sqliteScheduleDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/schedule-queries'
|
||||||
|
import { scheduleDbService as postgresScheduleDbService } from '@db-helper-postgres/dataAccessors/admin-apis/schedule-queries'
|
||||||
|
import { slotDbService as sqliteSlotDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/slot-queries'
|
||||||
|
import { slotDbService as postgresSlotDbService } from '@db-helper-postgres/dataAccessors/admin-apis/slot-queries'
|
||||||
|
import { staffUserDbService as sqliteStaffUserDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/staff-user-queries'
|
||||||
|
import { staffUserDbService as postgresStaffUserDbService } from '@db-helper-postgres/dataAccessors/admin-apis/staff-user-queries'
|
||||||
|
import { storeDbService as sqliteStoreDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/store-queries'
|
||||||
|
import { storeDbService as postgresStoreDbService } from '@db-helper-postgres/dataAccessors/admin-apis/store-queries'
|
||||||
|
import { tagDbService as sqliteTagDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/tag-queries'
|
||||||
|
import { tagDbService as postgresTagDbService } from '@db-helper-postgres/dataAccessors/admin-apis/tag-queries'
|
||||||
|
import { userDbService as sqliteUserDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/user-queries'
|
||||||
|
import { userDbService as postgresUserDbService } from '@db-helper-postgres/dataAccessors/admin-apis/user-queries'
|
||||||
|
import { vendorSnippetDbService as sqliteVendorSnippetDbService } from '@db-helper-sqlite/dataAccessors/admin-apis/vendor-snippets-queries'
|
||||||
|
import { vendorSnippetDbService as postgresVendorSnippetDbService } from '@db-helper-postgres/dataAccessors/admin-apis/vendor-snippets-queries'
|
||||||
|
|
||||||
|
const isSqlite = process.env.DB_DIALECT === 'sqlite'
|
||||||
|
|
||||||
|
export const bannerDbService = isSqlite ? sqliteBannerDbService : postgresBannerDbService
|
||||||
|
export const complaintDbService = isSqlite ? sqliteComplaintDbService : postgresComplaintDbService
|
||||||
|
export const constantDbService = isSqlite ? sqliteConstantDbService : postgresConstantDbService
|
||||||
|
export const couponDbService = isSqlite ? sqliteCouponDbService : postgresCouponDbService
|
||||||
|
export const orderDbService = isSqlite ? sqliteOrderDbService : postgresOrderDbService
|
||||||
|
export const productDbService = isSqlite ? sqliteProductDbService : postgresProductDbService
|
||||||
|
export const refundDbService = isSqlite ? sqliteRefundDbService : postgresRefundDbService
|
||||||
|
export const scheduleDbService = isSqlite ? sqliteScheduleDbService : postgresScheduleDbService
|
||||||
|
export const slotDbService = isSqlite ? sqliteSlotDbService : postgresSlotDbService
|
||||||
|
export const staffUserDbService = isSqlite ? sqliteStaffUserDbService : postgresStaffUserDbService
|
||||||
|
export const storeDbService = isSqlite ? sqliteStoreDbService : postgresStoreDbService
|
||||||
|
export const tagDbService = isSqlite ? sqliteTagDbService : postgresTagDbService
|
||||||
|
export const userDbService = isSqlite ? sqliteUserDbService : postgresUserDbService
|
||||||
|
export const vendorSnippetDbService = isSqlite ? sqliteVendorSnippetDbService : postgresVendorSnippetDbService
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,48 @@
|
||||||
export type { IUserBannerDbService, UserBanner } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
export type { IUserBannerDbService, UserBanner } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
||||||
// export { userBannerDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-banner-queries'
|
|
||||||
export { userBannerDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-banner-queries'
|
|
||||||
|
|
||||||
export type { IUserStoreDbService, Store as UserStore, StoreBasic } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-store-db-service.interface'
|
export type { IUserStoreDbService, Store as UserStore, StoreBasic } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-store-db-service.interface'
|
||||||
// export { userStoreDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-store-queries'
|
|
||||||
export { userStoreDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-store-queries'
|
|
||||||
|
|
||||||
export type { IUserAddressDbService, Address, NewAddress } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
export type { IUserAddressDbService, Address, NewAddress } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
||||||
// export { userAddressDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-address-queries'
|
|
||||||
export { userAddressDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-address-queries'
|
|
||||||
|
|
||||||
export type { IUserCartDbService, CartItem } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
export type { IUserCartDbService, CartItem } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
||||||
// export { userCartDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-cart-queries'
|
|
||||||
export { userCartDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-cart-queries'
|
|
||||||
|
|
||||||
export type { IUserComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
export type { IUserComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
||||||
// export { userComplaintDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-complaint-queries'
|
|
||||||
export { userComplaintDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-complaint-queries'
|
|
||||||
|
|
||||||
export type { IUserProductDbService, Product, Store as ProductStore, Review, ProductWithUnit } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
export type { IUserProductDbService, Product, Store as ProductStore, Review, ProductWithUnit } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
||||||
// export { userProductDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-product-queries'
|
|
||||||
export { userProductDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-product-queries'
|
|
||||||
|
|
||||||
export type { IUserAuthDbService, User, UserCred, UserDetail } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
export type { IUserAuthDbService, User, UserCred, UserDetail } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
||||||
// export { userAuthDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-auth-queries'
|
|
||||||
export { userAuthDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-auth-queries'
|
|
||||||
|
|
||||||
export type { IUserProfileDbService, User as ProfileUser, UserDetail as ProfileUserDetail, UserCred as ProfileUserCred, NotifCred, UnloggedToken } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-profile-db-service.interface'
|
export type { IUserProfileDbService, User as ProfileUser, UserDetail as ProfileUserDetail, UserCred as ProfileUserCred, NotifCred, UnloggedToken } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-profile-db-service.interface'
|
||||||
// export { userProfileDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-profile-queries'
|
|
||||||
export { userProfileDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-profile-queries'
|
|
||||||
|
|
||||||
export type { IUserSlotDbService, Slot } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-slot-db-service.interface'
|
export type { IUserSlotDbService, Slot } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-slot-db-service.interface'
|
||||||
// export { userSlotDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-slot-queries'
|
|
||||||
export { userSlotDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-slot-queries'
|
|
||||||
|
|
||||||
export type { IUserCouponDbService, Coupon, CouponWithRelations, ReservedCoupon } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
export type { IUserCouponDbService, Coupon, CouponWithRelations, ReservedCoupon } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
||||||
// export { userCouponDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-coupon-queries'
|
|
||||||
export { userCouponDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-coupon-queries'
|
|
||||||
|
|
||||||
export type { IUserOrderDbService, Order, OrderInsert, OrderItemInsert, OrderStatusInsert, Coupon as OrderCoupon } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
export type { IUserOrderDbService, Order, OrderInsert, OrderItemInsert, OrderStatusInsert, Coupon as OrderCoupon } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
||||||
// export { userOrderDbService } from '@/src/trpc/apis/user-apis/dataAccessors/postgres/user-order-queries'
|
|
||||||
export { userOrderDbService } from '@/src/trpc/apis/user-apis/dataAccessors/sqlite/user-order-queries'
|
import { userBannerDbService as sqliteUserBannerDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-banner-queries'
|
||||||
|
import { userBannerDbService as postgresUserBannerDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-banner-queries'
|
||||||
|
import { userStoreDbService as sqliteUserStoreDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-store-queries'
|
||||||
|
import { userStoreDbService as postgresUserStoreDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-store-queries'
|
||||||
|
import { userAddressDbService as sqliteUserAddressDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-address-queries'
|
||||||
|
import { userAddressDbService as postgresUserAddressDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-address-queries'
|
||||||
|
import { userCartDbService as sqliteUserCartDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-cart-queries'
|
||||||
|
import { userCartDbService as postgresUserCartDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-cart-queries'
|
||||||
|
import { userComplaintDbService as sqliteUserComplaintDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-complaint-queries'
|
||||||
|
import { userComplaintDbService as postgresUserComplaintDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-complaint-queries'
|
||||||
|
import { userProductDbService as sqliteUserProductDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-product-queries'
|
||||||
|
import { userProductDbService as postgresUserProductDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-product-queries'
|
||||||
|
import { userAuthDbService as sqliteUserAuthDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-auth-queries'
|
||||||
|
import { userAuthDbService as postgresUserAuthDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-auth-queries'
|
||||||
|
import { userProfileDbService as sqliteUserProfileDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-profile-queries'
|
||||||
|
import { userProfileDbService as postgresUserProfileDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-profile-queries'
|
||||||
|
import { userSlotDbService as sqliteUserSlotDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-slot-queries'
|
||||||
|
import { userSlotDbService as postgresUserSlotDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-slot-queries'
|
||||||
|
import { userCouponDbService as sqliteUserCouponDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-coupon-queries'
|
||||||
|
import { userCouponDbService as postgresUserCouponDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-coupon-queries'
|
||||||
|
import { userOrderDbService as sqliteUserOrderDbService } from '@db-helper-sqlite/dataAccessors/user-apis/user-order-queries'
|
||||||
|
import { userOrderDbService as postgresUserOrderDbService } from '@db-helper-postgres/dataAccessors/user-apis/user-order-queries'
|
||||||
|
|
||||||
|
const isSqlite = process.env.DB_DIALECT === 'sqlite'
|
||||||
|
|
||||||
|
export const userBannerDbService = isSqlite ? sqliteUserBannerDbService : postgresUserBannerDbService
|
||||||
|
export const userStoreDbService = isSqlite ? sqliteUserStoreDbService : postgresUserStoreDbService
|
||||||
|
export const userAddressDbService = isSqlite ? sqliteUserAddressDbService : postgresUserAddressDbService
|
||||||
|
export const userCartDbService = isSqlite ? sqliteUserCartDbService : postgresUserCartDbService
|
||||||
|
export const userComplaintDbService = isSqlite ? sqliteUserComplaintDbService : postgresUserComplaintDbService
|
||||||
|
export const userProductDbService = isSqlite ? sqliteUserProductDbService : postgresUserProductDbService
|
||||||
|
export const userAuthDbService = isSqlite ? sqliteUserAuthDbService : postgresUserAuthDbService
|
||||||
|
export const userProfileDbService = isSqlite ? sqliteUserProfileDbService : postgresUserProfileDbService
|
||||||
|
export const userSlotDbService = isSqlite ? sqliteUserSlotDbService : postgresUserSlotDbService
|
||||||
|
export const userCouponDbService = isSqlite ? sqliteUserCouponDbService : postgresUserCouponDbService
|
||||||
|
export const userOrderDbService = isSqlite ? sqliteUserOrderDbService : postgresUserOrderDbService
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
// "baseUrl": ".",
|
// "baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"],
|
"@/*": ["./*"],
|
||||||
|
"@db-helper-postgres/*": ["../db-helper-postgres/src/*"],
|
||||||
|
"@db-helper-sqlite/*": ["../db-helper-sqlite/src/*"],
|
||||||
"shared-types": ["../shared-types"],
|
"shared-types": ["../shared-types"],
|
||||||
"@commonTypes": ["../../packages/ui/shared-types"],
|
"@commonTypes": ["../../packages/ui/shared-types"],
|
||||||
"@commonTypes/*": ["../../packages/ui/shared-types/*"],
|
"@commonTypes/*": ["../../packages/ui/shared-types/*"],
|
||||||
|
|
@ -122,4 +124,3 @@
|
||||||
},
|
},
|
||||||
"include": ["src", "types", "index.ts", "../shared-types", "../../packages/shared"]
|
"include": ["src", "types", "index.ts", "../shared-types", "../../packages/shared"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1
apps/backend/types/db-dialect.d.ts
vendored
Normal file
1
apps/backend/types/db-dialect.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
declare const DB_DIALECT_TYPE: 'postgres'
|
||||||
|
|
@ -2,8 +2,8 @@ import 'dotenv/config'
|
||||||
import { defineConfig } from 'drizzle-kit'
|
import { defineConfig } from 'drizzle-kit'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
out: './drizzle/pg',
|
out: './drizzle',
|
||||||
schema: './src/db/schema-postgres.ts',
|
schema: './src/db/schema.ts',
|
||||||
dialect: 'postgresql',
|
dialect: 'postgresql',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: process.env.DATABASE_URL!,
|
url: process.env.DATABASE_URL!,
|
||||||
10
apps/db-helper-postgres/package.json
Normal file
10
apps/db-helper-postgres/package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "db-helper-postgres",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"drizzle-orm": "^0.45.1",
|
||||||
|
"pg": "^8.16.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { and, eq, gt, inArray } from 'drizzle-orm'
|
||||||
|
|
||||||
|
import { db } from '../../db/db_index'
|
||||||
|
import { deliverySlotInfo, productInfo, productSlots, productTags, units } from '../../db/schema'
|
||||||
|
|
||||||
|
type ProductSummaryRow = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
shortDescription: string | null
|
||||||
|
price: string
|
||||||
|
marketPrice: string
|
||||||
|
images: unknown
|
||||||
|
isOutOfStock: boolean | null
|
||||||
|
unitShortNotation: string
|
||||||
|
productQuantity: number | null
|
||||||
|
nextDeliveryDate: Date | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNextDeliveryDate = async (productId: number): Promise<Date | null> => {
|
||||||
|
const result = await db
|
||||||
|
.select({ deliveryTime: deliverySlotInfo.deliveryTime })
|
||||||
|
.from(productSlots)
|
||||||
|
.innerJoin(deliverySlotInfo, eq(productSlots.slotId, deliverySlotInfo.id))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(productSlots.productId, productId),
|
||||||
|
eq(deliverySlotInfo.isActive, true),
|
||||||
|
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderBy(deliverySlotInfo.deliveryTime)
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
return result[0]?.deliveryTime || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getProductsSummaryData = async (tagId?: number | null): Promise<ProductSummaryRow[]> => {
|
||||||
|
let productIds: number[] | null = null
|
||||||
|
|
||||||
|
if (tagId) {
|
||||||
|
const taggedProducts = await db
|
||||||
|
.select({ productId: productTags.productId })
|
||||||
|
.from(productTags)
|
||||||
|
.where(eq(productTags.tagId, tagId))
|
||||||
|
|
||||||
|
productIds = taggedProducts.map((taggedProduct) => taggedProduct.productId)
|
||||||
|
|
||||||
|
if (productIds.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereCondition = productIds && productIds.length > 0
|
||||||
|
? inArray(productInfo.id, productIds)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const productsWithUnits = await db
|
||||||
|
.select({
|
||||||
|
id: productInfo.id,
|
||||||
|
name: productInfo.name,
|
||||||
|
shortDescription: productInfo.shortDescription,
|
||||||
|
price: productInfo.price,
|
||||||
|
marketPrice: productInfo.marketPrice,
|
||||||
|
images: productInfo.images,
|
||||||
|
isOutOfStock: productInfo.isOutOfStock,
|
||||||
|
unitShortNotation: units.shortNotation,
|
||||||
|
productQuantity: productInfo.productQuantity,
|
||||||
|
})
|
||||||
|
.from(productInfo)
|
||||||
|
.innerJoin(units, eq(productInfo.unitId, units.id))
|
||||||
|
.where(whereCondition)
|
||||||
|
|
||||||
|
const productsWithDelivery = await Promise.all(
|
||||||
|
productsWithUnits.map(async (product) => {
|
||||||
|
const nextDeliveryDate = await getNextDeliveryDate(product.id)
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
nextDeliveryDate,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return productsWithDelivery
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { homeBanners } from '@/src/db/schema'
|
import { homeBanners } from '../../db/schema'
|
||||||
import { eq, desc } from 'drizzle-orm'
|
import { eq, desc } from 'drizzle-orm'
|
||||||
import { IBannerDbService, Banner, NewBanner } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
import { IBannerDbService, Banner, NewBanner } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
||||||
|
|
||||||
export class BannerDbService implements IBannerDbService {
|
export class BannerDbService implements IBannerDbService {
|
||||||
async getAllBanners(): Promise<Banner[]> {
|
async getAllBanners(): Promise<Banner[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { complaints, users } from '@/src/db/schema'
|
import { complaints, users } from '../../db/schema'
|
||||||
import { eq, desc, lt } from 'drizzle-orm'
|
import { eq, desc, lt } from 'drizzle-orm'
|
||||||
import { IComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
import { IComplaintDbService, Complaint, NewComplaint } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
||||||
|
|
||||||
export class ComplaintDbService implements IComplaintDbService {
|
export class ComplaintDbService implements IComplaintDbService {
|
||||||
async getComplaints(
|
async getComplaints(
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { keyValStore } from '@/src/db/schema'
|
import { keyValStore } from '../../db/schema'
|
||||||
import { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
import { IConstantDbService, Constant, NewConstant } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||||
|
|
||||||
export class ConstantDbService implements IConstantDbService {
|
export class ConstantDbService implements IConstantDbService {
|
||||||
async getAllConstants(): Promise<Constant[]> {
|
async getAllConstants(): Promise<Constant[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '@/src/db/schema'
|
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '../../db/schema'
|
||||||
import { eq, and, like, or, inArray, lt, asc } from 'drizzle-orm'
|
import { eq, and, like, or, inArray, lt, asc } from 'drizzle-orm'
|
||||||
import { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
import { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
||||||
|
|
||||||
export class CouponDbService implements ICouponDbService {
|
export class CouponDbService implements ICouponDbService {
|
||||||
async createCoupon(data: NewCoupon): Promise<Coupon> {
|
async createCoupon(data: NewCoupon): Promise<Coupon> {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import {
|
import {
|
||||||
orders,
|
orders,
|
||||||
orderItems,
|
orderItems,
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
productInfo,
|
productInfo,
|
||||||
units,
|
units,
|
||||||
paymentInfoTable,
|
paymentInfoTable,
|
||||||
} from '@/src/db/schema'
|
} from '../../db/schema'
|
||||||
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
IOrderDbService,
|
IOrderDbService,
|
||||||
|
|
@ -26,7 +26,7 @@ import {
|
||||||
OrderWithRelations,
|
OrderWithRelations,
|
||||||
OrderWithStatus,
|
OrderWithStatus,
|
||||||
OrderWithCouponUsages,
|
OrderWithCouponUsages,
|
||||||
} from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
} from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
||||||
|
|
||||||
export class OrderDbService implements IOrderDbService {
|
export class OrderDbService implements IOrderDbService {
|
||||||
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '@/src/db/schema'
|
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '../../db/schema'
|
||||||
import { eq, and, inArray, desc, sql } from 'drizzle-orm'
|
import { eq, and, inArray, desc, sql } from 'drizzle-orm'
|
||||||
import { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
import { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
||||||
|
|
||||||
export class ProductDbService implements IProductDbService {
|
export class ProductDbService implements IProductDbService {
|
||||||
async getAllProducts(): Promise<Product[]> {
|
async getAllProducts(): Promise<Product[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { refunds, orders, orderStatus, payments } from '@/src/db/schema'
|
import { refunds, orders, orderStatus, payments } from '../../db/schema'
|
||||||
import { eq, and } from 'drizzle-orm'
|
import { eq, and } from 'drizzle-orm'
|
||||||
import { IRefundDbService, Refund, NewRefund } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
import { IRefundDbService, Refund, NewRefund } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
||||||
|
|
||||||
export class RefundDbService implements IRefundDbService {
|
export class RefundDbService implements IRefundDbService {
|
||||||
async createRefund(data: NewRefund): Promise<Refund> {
|
async createRefund(data: NewRefund): Promise<Refund> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { productAvailabilitySchedules } from '@/src/db/schema'
|
import { productAvailabilitySchedules } from '../../db/schema'
|
||||||
import { eq, desc } from 'drizzle-orm'
|
import { eq, desc } from 'drizzle-orm'
|
||||||
import { IScheduleDbService, Schedule, NewSchedule } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
import { IScheduleDbService, Schedule, NewSchedule } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
||||||
|
|
||||||
export class ScheduleDbService implements IScheduleDbService {
|
export class ScheduleDbService implements IScheduleDbService {
|
||||||
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '@/src/db/schema'
|
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '../../db/schema'
|
||||||
import { eq, inArray, and, desc } from 'drizzle-orm'
|
import { eq, inArray, and, desc } from 'drizzle-orm'
|
||||||
import { ISlotDbService, Slot, NewSlot, ProductSlot, SlotWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
import { ISlotDbService, Slot, NewSlot, ProductSlot, SlotWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
||||||
|
|
||||||
export class SlotDbService implements ISlotDbService {
|
export class SlotDbService implements ISlotDbService {
|
||||||
async getAllSlots(): Promise<SlotWithRelations[]> {
|
async getAllSlots(): Promise<SlotWithRelations[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { staffUsers, staffRoles, users, userDetails, orders } from '@/src/db/schema'
|
import { staffUsers, staffRoles, users, userDetails, orders } from '../../db/schema'
|
||||||
import { eq, or, ilike, and, lt, desc } from 'drizzle-orm'
|
import { eq, or, ilike, and, lt, desc } from 'drizzle-orm'
|
||||||
import { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
import { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
||||||
|
|
||||||
export class StaffUserDbService implements IStaffUserDbService {
|
export class StaffUserDbService implements IStaffUserDbService {
|
||||||
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { storeInfo, productInfo } from '@/src/db/schema'
|
import { storeInfo, productInfo } from '../../db/schema'
|
||||||
import { eq, inArray } from 'drizzle-orm'
|
import { eq, inArray } from 'drizzle-orm'
|
||||||
import { IStoreDbService, Store, NewStore } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
import { IStoreDbService, Store, NewStore } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
||||||
|
|
||||||
export class StoreDbService implements IStoreDbService {
|
export class StoreDbService implements IStoreDbService {
|
||||||
async getAllStores(): Promise<Store[]> {
|
async getAllStores(): Promise<Store[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { productTagInfo } from '@/src/db/schema'
|
import { productTagInfo } from '../../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { ITagDbService, Tag, NewTag } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
import { ITagDbService, Tag, NewTag } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
||||||
|
|
||||||
export class TagDbService implements ITagDbService {
|
export class TagDbService implements ITagDbService {
|
||||||
async getAllTags(): Promise<Tag[]> {
|
async getAllTags(): Promise<Tag[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '@/src/db/schema'
|
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '../../db/schema'
|
||||||
import { eq, sql, desc, asc, count, max, inArray } from 'drizzle-orm'
|
import { eq, sql, desc, asc, count, max, inArray } from 'drizzle-orm'
|
||||||
import { IUserDbService, User, NewUser, UserDetail } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
import { IUserDbService, User, NewUser, UserDetail } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
||||||
|
|
||||||
export class UserDbService implements IUserDbService {
|
export class UserDbService implements IUserDbService {
|
||||||
async getUserById(id: number): Promise<User | undefined> {
|
async getUserById(id: number): Promise<User | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '@/src/db/schema'
|
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '../../db/schema'
|
||||||
import { eq, and, inArray, gt, asc, desc } from 'drizzle-orm'
|
import { eq, and, inArray, gt, asc, desc } from 'drizzle-orm'
|
||||||
import { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
import { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
||||||
|
|
||||||
export class VendorSnippetDbService implements IVendorSnippetDbService {
|
export class VendorSnippetDbService implements IVendorSnippetDbService {
|
||||||
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '@/src/db/schema'
|
import { addresses, orders, orderStatus, deliverySlotInfo } from '../../db/schema'
|
||||||
import { eq, and, gte } from 'drizzle-orm'
|
import { eq, and, gte } from 'drizzle-orm'
|
||||||
import { IUserAddressDbService, Address, NewAddress } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
import { IUserAddressDbService, Address, NewAddress } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
||||||
|
|
||||||
export class UserAddressDbService implements IUserAddressDbService {
|
export class UserAddressDbService implements IUserAddressDbService {
|
||||||
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { users, userCreds, userDetails, addresses, cartItems, complaints, couponApplicableUsers, couponUsage, notifCreds, notifications, orderItems, orderStatus, orders, payments, refunds, productReviews, reservedCoupons } from '@/src/db/schema'
|
import { users, userCreds, userDetails, addresses, cartItems, complaints, couponApplicableUsers, couponUsage, notifCreds, notifications, orderItems, orderStatus, orders, payments, refunds, productReviews, reservedCoupons } from '../../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { IUserAuthDbService, User, UserCred, UserDetail } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
import { IUserAuthDbService, User, UserCred, UserDetail } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
||||||
|
|
||||||
export class UserAuthDbService implements IUserAuthDbService {
|
export class UserAuthDbService implements IUserAuthDbService {
|
||||||
async getUserByEmail(email: string): Promise<User | undefined> {
|
async getUserByEmail(email: string): Promise<User | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { homeBanners } from '@/src/db/schema'
|
import { homeBanners } from '../../db/schema'
|
||||||
import { isNotNull, asc } from 'drizzle-orm'
|
import { isNotNull, asc } from 'drizzle-orm'
|
||||||
import { IUserBannerDbService, UserBanner } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
import { IUserBannerDbService, UserBanner } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
||||||
|
|
||||||
export class UserBannerDbService implements IUserBannerDbService {
|
export class UserBannerDbService implements IUserBannerDbService {
|
||||||
async getActiveBanners(): Promise<UserBanner[]> {
|
async getActiveBanners(): Promise<UserBanner[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { cartItems, productInfo, units } from '@/src/db/schema'
|
import { cartItems, productInfo, units } from '../../db/schema'
|
||||||
import { eq, and, sql } from 'drizzle-orm'
|
import { eq, and, sql } from 'drizzle-orm'
|
||||||
import { IUserCartDbService, CartItem } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
import { IUserCartDbService, CartItem } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
||||||
|
|
||||||
export class UserCartDbService implements IUserCartDbService {
|
export class UserCartDbService implements IUserCartDbService {
|
||||||
async getCartItemsWithProducts(userId: number) {
|
async getCartItemsWithProducts(userId: number) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { complaints } from '@/src/db/schema'
|
import { complaints } from '../../db/schema'
|
||||||
import { eq, asc } from 'drizzle-orm'
|
import { eq, asc } from 'drizzle-orm'
|
||||||
import { IUserComplaintDbService } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
import { IUserComplaintDbService } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
||||||
|
|
||||||
export class UserComplaintDbService implements IUserComplaintDbService {
|
export class UserComplaintDbService implements IUserComplaintDbService {
|
||||||
async getComplaintsByUserId(userId: number) {
|
async getComplaintsByUserId(userId: number) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '@/src/db/schema'
|
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '../../db/schema'
|
||||||
import { eq, and, or, gt, isNull } from 'drizzle-orm'
|
import { eq, and, or, gt, isNull } from 'drizzle-orm'
|
||||||
import { IUserCouponDbService, Coupon, ReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
import { IUserCouponDbService, Coupon, ReservedCoupon, CouponWithRelations } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
||||||
|
|
||||||
export class UserCouponDbService implements IUserCouponDbService {
|
export class UserCouponDbService implements IUserCouponDbService {
|
||||||
async getActiveCouponsForUser(userId: number): Promise<CouponWithRelations[]> {
|
async getActiveCouponsForUser(userId: number): Promise<CouponWithRelations[]> {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import {
|
import {
|
||||||
orders,
|
orders,
|
||||||
orderItems,
|
orderItems,
|
||||||
|
|
@ -12,12 +12,12 @@ import {
|
||||||
refunds,
|
refunds,
|
||||||
units,
|
units,
|
||||||
userDetails,
|
userDetails,
|
||||||
} from '@/src/db/schema'
|
} from '../../db/schema'
|
||||||
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
IUserOrderDbService,
|
IUserOrderDbService,
|
||||||
Order,
|
Order,
|
||||||
} from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
} from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
||||||
|
|
||||||
export class UserOrderDbService implements IUserOrderDbService {
|
export class UserOrderDbService implements IUserOrderDbService {
|
||||||
async getUserDetailByUserId(userId: number) {
|
async getUserDetailByUserId(userId: number) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '@/src/db/schema'
|
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '../../db/schema'
|
||||||
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
||||||
import { IUserProductDbService, Review } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
import { IUserProductDbService, Review } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
||||||
|
|
||||||
export class UserProductDbService implements IUserProductDbService {
|
export class UserProductDbService implements IUserProductDbService {
|
||||||
async getProductById(productId: number) {
|
async getProductById(productId: number) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { users, userDetails, userCreds, notifCreds, unloggedUserTokens } from '@/src/db/schema'
|
import { users, userDetails, userCreds, notifCreds, unloggedUserTokens } from '../../db/schema'
|
||||||
import { eq, and } from 'drizzle-orm'
|
import { eq, and } from 'drizzle-orm'
|
||||||
import { IUserProfileDbService, User, UserDetail, UserCred, NotifCred, UnloggedToken } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-profile-db-service.interface'
|
import { IUserProfileDbService, User, UserDetail, UserCred, NotifCred, UnloggedToken } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-profile-db-service.interface'
|
||||||
|
|
||||||
export class UserProfileDbService implements IUserProfileDbService {
|
export class UserProfileDbService implements IUserProfileDbService {
|
||||||
async getUserById(userId: number): Promise<User | undefined> {
|
async getUserById(userId: number): Promise<User | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { deliverySlotInfo, productInfo } from '@/src/db/schema'
|
import { deliverySlotInfo, productInfo } from '../../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { IUserSlotDbService, Slot } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-slot-db-service.interface'
|
import { IUserSlotDbService, Slot } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-slot-db-service.interface'
|
||||||
|
|
||||||
export class UserSlotDbService implements IUserSlotDbService {
|
export class UserSlotDbService implements IUserSlotDbService {
|
||||||
async getActiveSlots(): Promise<Slot[]> {
|
async getActiveSlots(): Promise<Slot[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { storeInfo, productInfo, units } from '@/src/db/schema'
|
import { storeInfo, productInfo, units } from '../../db/schema'
|
||||||
import { eq, and, sql } from 'drizzle-orm'
|
import { eq, and, sql } from 'drizzle-orm'
|
||||||
import { IUserStoreDbService } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-store-db-service.interface'
|
import { IUserStoreDbService } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-store-db-service.interface'
|
||||||
|
|
||||||
export class UserStoreDbService implements IUserStoreDbService {
|
export class UserStoreDbService implements IUserStoreDbService {
|
||||||
async getStoresWithProductCount(): Promise<Array<{ id: number; name: string; description: string | null; imageUrl: string | null; productCount: number }>> {
|
async getStoresWithProductCount(): Promise<Array<{ id: number; name: string; description: string | null; imageUrl: string | null; productCount: number }>> {
|
||||||
10
apps/db-helper-postgres/src/db/db_index.ts
Normal file
10
apps/db-helper-postgres/src/db/db_index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { drizzle } from 'drizzle-orm/node-postgres'
|
||||||
|
import * as schema from './schema'
|
||||||
|
|
||||||
|
const db = drizzle({
|
||||||
|
connection: process.env.DATABASE_URL!,
|
||||||
|
casing: 'snake_case',
|
||||||
|
schema,
|
||||||
|
})
|
||||||
|
|
||||||
|
export { db }
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
* This was a one time script to change the composition of the signed urls
|
* This was a one time script to change the composition of the signed urls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from './db_index'
|
||||||
import {
|
import {
|
||||||
userDetails,
|
userDetails,
|
||||||
productInfo,
|
productInfo,
|
||||||
productTagInfo,
|
productTagInfo,
|
||||||
complaints
|
complaints
|
||||||
} from '@/src/db/schema';
|
} from './schema';
|
||||||
import { eq, not, isNull } from 'drizzle-orm';
|
import { eq, not, isNull } from 'drizzle-orm';
|
||||||
|
|
||||||
const S3_DOMAIN = 'https://s3.sgp.io.cloud.ovh.net';
|
const S3_DOMAIN = 'https://s3.sgp.io.cloud.ovh.net';
|
||||||
706
apps/db-helper-postgres/src/db/schema.ts
Normal file
706
apps/db-helper-postgres/src/db/schema.ts
Normal file
|
|
@ -0,0 +1,706 @@
|
||||||
|
import { pgTable, pgSchema, integer, varchar, date, boolean, timestamp, numeric, jsonb, pgEnum, unique, real, text, check, decimal } from "drizzle-orm/pg-core";
|
||||||
|
import { relations, sql } from "drizzle-orm";
|
||||||
|
|
||||||
|
const mf = pgSchema('mf');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const users = mf.table('users', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar({ length: 255 }),
|
||||||
|
email: varchar({ length: 255 }),
|
||||||
|
mobile: varchar({ length: 255 }),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_email: unique('unique_email').on(t.email),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userDetails = mf.table('user_details', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id).unique(),
|
||||||
|
bio: varchar('bio', { length: 500 }),
|
||||||
|
dateOfBirth: date('date_of_birth'),
|
||||||
|
gender: varchar('gender', { length: 20 }),
|
||||||
|
occupation: varchar('occupation', { length: 100 }),
|
||||||
|
profileImage: varchar('profile_image', { length: 500 }),
|
||||||
|
isSuspended: boolean('is_suspended').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const userCreds = mf.table('user_creds', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
userPassword: varchar('user_password', { length: 255 }).notNull(),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const addresses = mf.table('addresses', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
name: varchar('name', { length: 255 }).notNull(),
|
||||||
|
phone: varchar('phone', { length: 15 }).notNull(),
|
||||||
|
addressLine1: varchar('address_line1', { length: 255 }).notNull(),
|
||||||
|
addressLine2: varchar('address_line2', { length: 255 }),
|
||||||
|
city: varchar('city', { length: 100 }).notNull(),
|
||||||
|
state: varchar('state', { length: 100 }).notNull(),
|
||||||
|
pincode: varchar('pincode', { length: 10 }).notNull(),
|
||||||
|
isDefault: boolean('is_default').notNull().default(false),
|
||||||
|
latitude: real('latitude'),
|
||||||
|
longitude: real('longitude'),
|
||||||
|
googleMapsUrl: varchar('google_maps_url', { length: 500 }),
|
||||||
|
adminLatitude: real('admin_latitude'),
|
||||||
|
adminLongitude: real('admin_longitude'),
|
||||||
|
zoneId: integer('zone_id').references(() => addressZones.id),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const addressZones = mf.table('address_zones', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
zoneName: varchar('zone_name', { length: 255 }).notNull(),
|
||||||
|
addedAt: timestamp('added_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const addressAreas = mf.table('address_areas', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
placeName: varchar('place_name', { length: 255 }).notNull(),
|
||||||
|
zoneId: integer('zone_id').references(() => addressZones.id),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const staffUsers = mf.table('staff_users', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar({ length: 255 }).notNull(),
|
||||||
|
password: varchar({ length: 255 }).notNull(),
|
||||||
|
staffRoleId: integer('staff_role_id').references(() => staffRoles.id),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const storeInfo = mf.table('store_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar({ length: 255 }).notNull(),
|
||||||
|
description: varchar({ length: 500 }),
|
||||||
|
imageUrl: varchar('image_url', { length: 500 }),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
owner: integer('owner').notNull().references(() => staffUsers.id),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const units = mf.table('units', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
shortNotation: varchar('short_notation', { length: 50 }).notNull(),
|
||||||
|
fullName: varchar('full_name', { length: 100 }).notNull(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_short_notation: unique('unique_short_notation').on(t.shortNotation),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productAvailabilityActionEnum = pgEnum('product_availability_action', ['in', 'out']);
|
||||||
|
|
||||||
|
export const productInfo = mf.table('product_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar({ length: 255 }).notNull(),
|
||||||
|
shortDescription: varchar('short_description', { length: 500 }),
|
||||||
|
longDescription: varchar('long_description', { length: 1000 }),
|
||||||
|
unitId: integer('unit_id').notNull().references(() => units.id),
|
||||||
|
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
marketPrice: numeric('market_price', { precision: 10, scale: 2 }),
|
||||||
|
images: jsonb('images'),
|
||||||
|
isOutOfStock: boolean('is_out_of_stock').notNull().default(false),
|
||||||
|
isSuspended: boolean('is_suspended').notNull().default(false),
|
||||||
|
isFlashAvailable: boolean('is_flash_available').notNull().default(false),
|
||||||
|
flashPrice: numeric('flash_price', { precision: 10, scale: 2 }),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
incrementStep: real('increment_step').notNull().default(1),
|
||||||
|
productQuantity: real('product_quantity').notNull().default(1),
|
||||||
|
storeId: integer('store_id').references(() => storeInfo.id),
|
||||||
|
scheduledAvailability: boolean('scheduled_availability').notNull().default(true),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productAvailabilitySchedules = mf.table('product_availability_schedules', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
time: varchar('time', { length: 10 }).notNull(),
|
||||||
|
scheduleName: varchar('schedule_name', { length: 255 }).notNull().unique(),
|
||||||
|
action: productAvailabilityActionEnum('action').notNull(),
|
||||||
|
productIds: integer('product_ids').array().notNull().default([]),
|
||||||
|
groupIds: integer('group_ids').array().notNull().default([]),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
lastUpdated: timestamp('last_updated').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productGroupInfo = mf.table('product_group_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
groupName: varchar('group_name', { length: 255 }).notNull(),
|
||||||
|
description: varchar({ length: 500 }),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productGroupMembership = mf.table('product_group_membership', {
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
groupId: integer('group_id').notNull().references(() => productGroupInfo.id),
|
||||||
|
addedAt: timestamp('added_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
pk: unique('product_group_membership_pk').on(t.productId, t.groupId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const homeBanners = mf.table('home_banners', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar('name', { length: 255 }).notNull(),
|
||||||
|
imageUrl: varchar('image_url', { length: 500 }).notNull(),
|
||||||
|
description: varchar('description', { length: 500 }),
|
||||||
|
productIds: integer('product_ids').array(),
|
||||||
|
redirectUrl: varchar('redirect_url', { length: 500 }),
|
||||||
|
serialNum: integer('serial_num'),
|
||||||
|
isActive: boolean('is_active').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
lastUpdated: timestamp('last_updated').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productReviews = mf.table('product_reviews', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
reviewBody: text('review_body').notNull(),
|
||||||
|
imageUrls: jsonb('image_urls').$defaultFn(() => []),
|
||||||
|
reviewTime: timestamp('review_time').notNull().defaultNow(),
|
||||||
|
ratings: real('ratings').notNull(),
|
||||||
|
adminResponse: text('admin_response'),
|
||||||
|
adminResponseImages: jsonb('admin_response_images').$defaultFn(() => []),
|
||||||
|
}, (t) => ({
|
||||||
|
ratingCheck: check('rating_check', sql`${t.ratings} >= 1 AND ${t.ratings} <= 5`),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const uploadStatusEnum = pgEnum('upload_status', ['pending', 'claimed']);
|
||||||
|
|
||||||
|
export const staffRoleEnum = pgEnum('staff_role', ['super_admin', 'admin', 'marketer', 'delivery_staff']);
|
||||||
|
|
||||||
|
export const staffPermissionEnum = pgEnum('staff_permission', ['crud_product', 'make_coupon', 'crud_staff_users']);
|
||||||
|
|
||||||
|
export const uploadUrlStatus = mf.table('upload_url_status', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
key: varchar('key', { length: 500 }).notNull(),
|
||||||
|
status: uploadStatusEnum('status').notNull().default('pending'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productTagInfo = mf.table('product_tag_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
tagName: varchar('tag_name', { length: 100 }).notNull().unique(),
|
||||||
|
tagDescription: varchar('tag_description', { length: 500 }),
|
||||||
|
imageUrl: varchar('image_url', { length: 500 }),
|
||||||
|
isDashboardTag: boolean('is_dashboard_tag').notNull().default(false),
|
||||||
|
relatedStores: jsonb('related_stores').$defaultFn(() => []),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productTags = mf.table('product_tags', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
tagId: integer('tag_id').notNull().references(() => productTagInfo.id),
|
||||||
|
assignedAt: timestamp('assigned_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_product_tag: unique('unique_product_tag').on(t.productId, t.tagId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const deliverySlotInfo = mf.table('delivery_slot_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
deliveryTime: timestamp('delivery_time').notNull(),
|
||||||
|
freezeTime: timestamp('freeze_time').notNull(),
|
||||||
|
isActive: boolean('is_active').notNull().default(true),
|
||||||
|
isFlash: boolean('is_flash').notNull().default(false),
|
||||||
|
isCapacityFull: boolean('is_capacity_full').notNull().default(false),
|
||||||
|
deliverySequence: jsonb('delivery_sequence').$defaultFn(() => {}),
|
||||||
|
groupIds: jsonb('group_ids').$defaultFn(() => []),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const vendorSnippets = mf.table('vendor_snippets', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
snippetCode: varchar('snippet_code', { length: 255 }).notNull().unique(),
|
||||||
|
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
||||||
|
isPermanent: boolean('is_permanent').notNull().default(false),
|
||||||
|
productIds: integer('product_ids').array().notNull(),
|
||||||
|
validTill: timestamp('valid_till'),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const vendorSnippetsRelations = relations(vendorSnippets, ({ one }) => ({
|
||||||
|
slot: one(deliverySlotInfo, { fields: [vendorSnippets.slotId], references: [deliverySlotInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productSlots = mf.table('product_slots', {
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
slotId: integer('slot_id').notNull().references(() => deliverySlotInfo.id),
|
||||||
|
}, (t) => ({
|
||||||
|
pk: unique('product_slot_pk').on(t.productId, t.slotId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const specialDeals = mf.table('special_deals', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
quantity: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
validTill: timestamp('valid_till').notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const orders = mf.table('orders', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
addressId: integer('address_id').notNull().references(() => addresses.id),
|
||||||
|
slotId: integer('slot_id').references(() => deliverySlotInfo.id),
|
||||||
|
isCod: boolean('is_cod').notNull().default(false),
|
||||||
|
isOnlinePayment: boolean('is_online_payment').notNull().default(false),
|
||||||
|
paymentInfoId: integer('payment_info_id').references(() => paymentInfoTable.id),
|
||||||
|
totalAmount: numeric('total_amount', { precision: 10, scale: 2 }).notNull(),
|
||||||
|
deliveryCharge: numeric('delivery_charge', { precision: 10, scale: 2 }).notNull().default('0'),
|
||||||
|
readableId: integer('readable_id').notNull(),
|
||||||
|
adminNotes: text('admin_notes'),
|
||||||
|
userNotes: text('user_notes'),
|
||||||
|
orderGroupId: varchar('order_group_id', { length: 255 }),
|
||||||
|
orderGroupProportion: decimal('order_group_proportion', { precision: 10, scale: 4 }),
|
||||||
|
isFlashDelivery: boolean('is_flash_delivery').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const orderItems = mf.table('order_items', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
orderId: integer('order_id').notNull().references(() => orders.id),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
quantity: varchar('quantity', { length: 50 }).notNull(),
|
||||||
|
price: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
discountedPrice: numeric('discounted_price', { precision: 10, scale: 2 }),
|
||||||
|
is_packaged: boolean('is_packaged').notNull().default(false),
|
||||||
|
is_package_verified: boolean('is_package_verified').notNull().default(false),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const paymentStatusEnum = pgEnum('payment_status', ['pending', 'success', 'cod', 'failed']);
|
||||||
|
|
||||||
|
export const orderStatus = mf.table('order_status', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
orderTime: timestamp('order_time').notNull().defaultNow(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
orderId: integer('order_id').notNull().references(() => orders.id),
|
||||||
|
isPackaged: boolean('is_packaged').notNull().default(false),
|
||||||
|
isDelivered: boolean('is_delivered').notNull().default(false),
|
||||||
|
isCancelled: boolean('is_cancelled').notNull().default(false),
|
||||||
|
cancelReason: varchar('cancel_reason', { length: 255 }),
|
||||||
|
isCancelledByAdmin: boolean('is_cancelled_by_admin'),
|
||||||
|
paymentStatus: paymentStatusEnum('payment_state').notNull().default('pending'),
|
||||||
|
cancellationUserNotes: text('cancellation_user_notes'),
|
||||||
|
cancellationAdminNotes: text('cancellation_admin_notes'),
|
||||||
|
cancellationReviewed: boolean('cancellation_reviewed').notNull().default(false),
|
||||||
|
cancellationReviewedAt: timestamp('cancellation_reviewed_at'),
|
||||||
|
refundCouponId: integer('refund_coupon_id').references(() => coupons.id),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const paymentInfoTable = mf.table('payment_info', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
status: varchar({ length: 50 }).notNull(),
|
||||||
|
gateway: varchar({ length: 50 }).notNull(),
|
||||||
|
orderId: varchar('order_id', { length: 500 }),
|
||||||
|
token: varchar({ length: 500 }),
|
||||||
|
merchantOrderId: varchar('merchant_order_id', { length: 255 }).notNull().unique(),
|
||||||
|
payload: jsonb('payload'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const payments = mf.table('payments', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
status: varchar({ length: 50 }).notNull(),
|
||||||
|
gateway: varchar({ length: 50 }).notNull(),
|
||||||
|
orderId: integer('order_id').notNull().references(() => orders.id),
|
||||||
|
token: varchar({ length: 500 }),
|
||||||
|
merchantOrderId: varchar('merchant_order_id', { length: 255 }).notNull().unique(),
|
||||||
|
payload: jsonb('payload'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const refunds = mf.table('refunds', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
orderId: integer('order_id').notNull().references(() => orders.id),
|
||||||
|
refundAmount: numeric('refund_amount', { precision: 10, scale: 2 }),
|
||||||
|
refundStatus: varchar('refund_status', { length: 50 }).default('none'),
|
||||||
|
merchantRefundId: varchar('merchant_refund_id', { length: 255 }),
|
||||||
|
refundProcessedAt: timestamp('refund_processed_at'),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const keyValStore = mf.table('key_val_store', {
|
||||||
|
key: varchar('key', { length: 255 }).primaryKey(),
|
||||||
|
value: jsonb('value'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const notifications = mf.table('notifications', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
title: varchar({ length: 255 }).notNull(),
|
||||||
|
body: varchar({ length: 512 }).notNull(),
|
||||||
|
type: varchar({ length: 50 }),
|
||||||
|
isRead: boolean('is_read').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const productCategories = mf.table('product_categories', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
name: varchar({ length: 255 }).notNull(),
|
||||||
|
description: varchar({ length: 500 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const cartItems = mf.table('cart_items', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
quantity: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
addedAt: timestamp('added_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_user_product: unique('unique_user_product').on(t.userId, t.productId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const complaints = mf.table('complaints', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
orderId: integer('order_id').references(() => orders.id),
|
||||||
|
complaintBody: varchar('complaint_body', { length: 1000 }).notNull(),
|
||||||
|
images: jsonb('images'),
|
||||||
|
response: varchar('response', { length: 1000 }),
|
||||||
|
isResolved: boolean('is_resolved').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const coupons = mf.table('coupons', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
couponCode: varchar('coupon_code', { length: 50 }).notNull().unique('unique_coupon_code'),
|
||||||
|
isUserBased: boolean('is_user_based').notNull().default(false),
|
||||||
|
discountPercent: numeric('discount_percent', { precision: 5, scale: 2 }),
|
||||||
|
flatDiscount: numeric('flat_discount', { precision: 10, scale: 2 }),
|
||||||
|
minOrder: numeric('min_order', { precision: 10, scale: 2 }),
|
||||||
|
productIds: jsonb('product_ids'),
|
||||||
|
createdBy: integer('created_by').references(() => staffUsers.id),
|
||||||
|
maxValue: numeric('max_value', { precision: 10, scale: 2 }),
|
||||||
|
isApplyForAll: boolean('is_apply_for_all').notNull().default(false),
|
||||||
|
validTill: timestamp('valid_till'),
|
||||||
|
maxLimitForUser: integer('max_limit_for_user'),
|
||||||
|
isInvalidated: boolean('is_invalidated').notNull().default(false),
|
||||||
|
exclusiveApply: boolean('exclusive_apply').notNull().default(false),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const couponUsage = mf.table('coupon_usage', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
||||||
|
orderId: integer('order_id').references(() => orders.id),
|
||||||
|
orderItemId: integer('order_item_id').references(() => orderItems.id),
|
||||||
|
usedAt: timestamp('used_at').notNull().defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const couponApplicableUsers = mf.table('coupon_applicable_users', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_coupon_user: unique('unique_coupon_user').on(t.couponId, t.userId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const couponApplicableProducts = mf.table('coupon_applicable_products', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
couponId: integer('coupon_id').notNull().references(() => coupons.id),
|
||||||
|
productId: integer('product_id').notNull().references(() => productInfo.id),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_coupon_product: unique('unique_coupon_product').on(t.couponId, t.productId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userIncidents = mf.table('user_incidents', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
orderId: integer('order_id').references(() => orders.id),
|
||||||
|
dateAdded: timestamp('date_added').notNull().defaultNow(),
|
||||||
|
adminComment: text('admin_comment'),
|
||||||
|
addedBy: integer('added_by').references(() => staffUsers.id),
|
||||||
|
negativityScore: integer('negativity_score'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const reservedCoupons = mf.table('reserved_coupons', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
secretCode: varchar('secret_code', { length: 50 }).notNull().unique(),
|
||||||
|
couponCode: varchar('coupon_code', { length: 50 }).notNull(),
|
||||||
|
discountPercent: numeric('discount_percent', { precision: 5, scale: 2 }),
|
||||||
|
flatDiscount: numeric('flat_discount', { precision: 10, scale: 2 }),
|
||||||
|
minOrder: numeric('min_order', { precision: 10, scale: 2 }),
|
||||||
|
productIds: jsonb('product_ids'),
|
||||||
|
maxValue: numeric('max_value', { precision: 10, scale: 2 }),
|
||||||
|
validTill: timestamp('valid_till'),
|
||||||
|
maxLimitForUser: integer('max_limit_for_user'),
|
||||||
|
exclusiveApply: boolean('exclusive_apply').notNull().default(false),
|
||||||
|
isRedeemed: boolean('is_redeemed').notNull().default(false),
|
||||||
|
redeemedBy: integer('redeemed_by').references(() => users.id),
|
||||||
|
redeemedAt: timestamp('redeemed_at'),
|
||||||
|
createdBy: integer('created_by').notNull().references(() => staffUsers.id),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_secret_code: unique('unique_secret_code').on(t.secretCode),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const notifCreds = mf.table('notif_creds', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
token: varchar({ length: 500 }).notNull().unique(),
|
||||||
|
addedAt: timestamp('added_at').notNull().defaultNow(),
|
||||||
|
userId: integer('user_id').notNull().references(() => users.id),
|
||||||
|
lastVerified: timestamp('last_verified'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const unloggedUserTokens = mf.table('unlogged_user_tokens', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
token: varchar({ length: 500 }).notNull().unique(),
|
||||||
|
addedAt: timestamp('added_at').notNull().defaultNow(),
|
||||||
|
lastVerified: timestamp('last_verified'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const userNotifications = mf.table('user_notifications', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
title: varchar('title', { length: 255 }).notNull(),
|
||||||
|
imageUrl: varchar('image_url', { length: 500 }),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
body: text('body').notNull(),
|
||||||
|
applicableUsers: jsonb('applicable_users'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const staffRoles = mf.table('staff_roles', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
roleName: staffRoleEnum('role_name').notNull(),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_role_name: unique('unique_role_name').on(t.roleName),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffPermissions = mf.table('staff_permissions', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
permissionName: staffPermissionEnum('permission_name').notNull(),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_permission_name: unique('unique_permission_name').on(t.permissionName),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffRolePermissions = mf.table('staff_role_permissions', {
|
||||||
|
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||||
|
staffRoleId: integer('staff_role_id').notNull().references(() => staffRoles.id),
|
||||||
|
staffPermissionId: integer('staff_permission_id').notNull().references(() => staffPermissions.id),
|
||||||
|
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||||
|
}, (t) => ({
|
||||||
|
unq_role_permission: unique('unique_role_permission').on(t.staffRoleId, t.staffPermissionId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
export const usersRelations = relations(users, ({ many, one }) => ({
|
||||||
|
addresses: many(addresses),
|
||||||
|
orders: many(orders),
|
||||||
|
notifications: many(notifications),
|
||||||
|
cartItems: many(cartItems),
|
||||||
|
userCreds: one(userCreds),
|
||||||
|
coupons: many(coupons),
|
||||||
|
couponUsages: many(couponUsage),
|
||||||
|
applicableCoupons: many(couponApplicableUsers),
|
||||||
|
userDetails: one(userDetails),
|
||||||
|
notifCreds: many(notifCreds),
|
||||||
|
userIncidents: many(userIncidents),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userCredsRelations = relations(userCreds, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [userCreds.userId], references: [users.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffUsersRelations = relations(staffUsers, ({ one, many }) => ({
|
||||||
|
role: one(staffRoles, { fields: [staffUsers.staffRoleId], references: [staffRoles.id] }),
|
||||||
|
coupons: many(coupons),
|
||||||
|
stores: many(storeInfo),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const addressesRelations = relations(addresses, ({ one, many }) => ({
|
||||||
|
user: one(users, { fields: [addresses.userId], references: [users.id] }),
|
||||||
|
orders: many(orders),
|
||||||
|
zone: one(addressZones, { fields: [addresses.zoneId], references: [addressZones.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const unitsRelations = relations(units, ({ many }) => ({
|
||||||
|
products: many(productInfo),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productInfoRelations = relations(productInfo, ({ one, many }) => ({
|
||||||
|
unit: one(units, { fields: [productInfo.unitId], references: [units.id] }),
|
||||||
|
store: one(storeInfo, { fields: [productInfo.storeId], references: [storeInfo.id] }),
|
||||||
|
productSlots: many(productSlots),
|
||||||
|
specialDeals: many(specialDeals),
|
||||||
|
orderItems: many(orderItems),
|
||||||
|
cartItems: many(cartItems),
|
||||||
|
tags: many(productTags),
|
||||||
|
applicableCoupons: many(couponApplicableProducts),
|
||||||
|
reviews: many(productReviews),
|
||||||
|
groups: many(productGroupMembership),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productTagInfoRelations = relations(productTagInfo, ({ many }) => ({
|
||||||
|
products: many(productTags),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productTagsRelations = relations(productTags, ({ one }) => ({
|
||||||
|
product: one(productInfo, { fields: [productTags.productId], references: [productInfo.id] }),
|
||||||
|
tag: one(productTagInfo, { fields: [productTags.tagId], references: [productTagInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const deliverySlotInfoRelations = relations(deliverySlotInfo, ({ many }) => ({
|
||||||
|
productSlots: many(productSlots),
|
||||||
|
orders: many(orders),
|
||||||
|
vendorSnippets: many(vendorSnippets),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productSlotsRelations = relations(productSlots, ({ one }) => ({
|
||||||
|
product: one(productInfo, { fields: [productSlots.productId], references: [productInfo.id] }),
|
||||||
|
slot: one(deliverySlotInfo, { fields: [productSlots.slotId], references: [deliverySlotInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const specialDealsRelations = relations(specialDeals, ({ one }) => ({
|
||||||
|
product: one(productInfo, { fields: [specialDeals.productId], references: [productInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ordersRelations = relations(orders, ({ one, many }) => ({
|
||||||
|
user: one(users, { fields: [orders.userId], references: [users.id] }),
|
||||||
|
address: one(addresses, { fields: [orders.addressId], references: [addresses.id] }),
|
||||||
|
slot: one(deliverySlotInfo, { fields: [orders.slotId], references: [deliverySlotInfo.id] }),
|
||||||
|
orderItems: many(orderItems),
|
||||||
|
payment: one(payments),
|
||||||
|
paymentInfo: one(paymentInfoTable, { fields: [orders.paymentInfoId], references: [paymentInfoTable.id] }),
|
||||||
|
orderStatus: many(orderStatus),
|
||||||
|
refunds: many(refunds),
|
||||||
|
couponUsages: many(couponUsage),
|
||||||
|
userIncidents: many(userIncidents),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const orderItemsRelations = relations(orderItems, ({ one }) => ({
|
||||||
|
order: one(orders, { fields: [orderItems.orderId], references: [orders.id] }),
|
||||||
|
product: one(productInfo, { fields: [orderItems.productId], references: [productInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const orderStatusRelations = relations(orderStatus, ({ one }) => ({
|
||||||
|
order: one(orders, { fields: [orderStatus.orderId], references: [orders.id] }),
|
||||||
|
user: one(users, { fields: [orderStatus.userId], references: [users.id] }),
|
||||||
|
refundCoupon: one(coupons, { fields: [orderStatus.refundCouponId], references: [coupons.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const paymentInfoRelations = relations(paymentInfoTable, ({ one }) => ({
|
||||||
|
order: one(orders, { fields: [paymentInfoTable.id], references: [orders.paymentInfoId] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const paymentsRelations = relations(payments, ({ one }) => ({
|
||||||
|
order: one(orders, { fields: [payments.orderId], references: [orders.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const refundsRelations = relations(refunds, ({ one }) => ({
|
||||||
|
order: one(orders, { fields: [refunds.orderId], references: [orders.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [notifications.userId], references: [users.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productCategoriesRelations = relations(productCategories, ({}) => ({}));
|
||||||
|
|
||||||
|
export const cartItemsRelations = relations(cartItems, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [cartItems.userId], references: [users.id] }),
|
||||||
|
product: one(productInfo, { fields: [cartItems.productId], references: [productInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const complaintsRelations = relations(complaints, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [complaints.userId], references: [users.id] }),
|
||||||
|
order: one(orders, { fields: [complaints.orderId], references: [orders.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const couponsRelations = relations(coupons, ({ one, many }) => ({
|
||||||
|
creator: one(staffUsers, { fields: [coupons.createdBy], references: [staffUsers.id] }),
|
||||||
|
usages: many(couponUsage),
|
||||||
|
applicableUsers: many(couponApplicableUsers),
|
||||||
|
applicableProducts: many(couponApplicableProducts),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const couponUsageRelations = relations(couponUsage, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [couponUsage.userId], references: [users.id] }),
|
||||||
|
coupon: one(coupons, { fields: [couponUsage.couponId], references: [coupons.id] }),
|
||||||
|
order: one(orders, { fields: [couponUsage.orderId], references: [orders.id] }),
|
||||||
|
orderItem: one(orderItems, { fields: [couponUsage.orderItemId], references: [orderItems.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userDetailsRelations = relations(userDetails, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [userDetails.userId], references: [users.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const notifCredsRelations = relations(notifCreds, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [notifCreds.userId], references: [users.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userNotificationsRelations = relations(userNotifications, ({}) => ({
|
||||||
|
// No relations needed for now
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const storeInfoRelations = relations(storeInfo, ({ one, many }) => ({
|
||||||
|
owner: one(staffUsers, { fields: [storeInfo.owner], references: [staffUsers.id] }),
|
||||||
|
products: many(productInfo),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const couponApplicableUsersRelations = relations(couponApplicableUsers, ({ one }) => ({
|
||||||
|
coupon: one(coupons, { fields: [couponApplicableUsers.couponId], references: [coupons.id] }),
|
||||||
|
user: one(users, { fields: [couponApplicableUsers.userId], references: [users.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const couponApplicableProductsRelations = relations(couponApplicableProducts, ({ one }) => ({
|
||||||
|
coupon: one(coupons, { fields: [couponApplicableProducts.couponId], references: [coupons.id] }),
|
||||||
|
product: one(productInfo, { fields: [couponApplicableProducts.productId], references: [productInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const reservedCouponsRelations = relations(reservedCoupons, ({ one }) => ({
|
||||||
|
redeemedUser: one(users, { fields: [reservedCoupons.redeemedBy], references: [users.id] }),
|
||||||
|
creator: one(staffUsers, { fields: [reservedCoupons.createdBy], references: [staffUsers.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productReviewsRelations = relations(productReviews, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [productReviews.userId], references: [users.id] }),
|
||||||
|
product: one(productInfo, { fields: [productReviews.productId], references: [productInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const addressZonesRelations = relations(addressZones, ({ many }) => ({
|
||||||
|
addresses: many(addresses),
|
||||||
|
areas: many(addressAreas),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const addressAreasRelations = relations(addressAreas, ({ one }) => ({
|
||||||
|
zone: one(addressZones, { fields: [addressAreas.zoneId], references: [addressZones.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productGroupInfoRelations = relations(productGroupInfo, ({ many }) => ({
|
||||||
|
memberships: many(productGroupMembership),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productGroupMembershipRelations = relations(productGroupMembership, ({ one }) => ({
|
||||||
|
product: one(productInfo, { fields: [productGroupMembership.productId], references: [productInfo.id] }),
|
||||||
|
group: one(productGroupInfo, { fields: [productGroupMembership.groupId], references: [productGroupInfo.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const homeBannersRelations = relations(homeBanners, ({}) => ({
|
||||||
|
// Relations for productIds array would be more complex, skipping for now
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffRolesRelations = relations(staffRoles, ({ many }) => ({
|
||||||
|
staffUsers: many(staffUsers),
|
||||||
|
rolePermissions: many(staffRolePermissions),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffPermissionsRelations = relations(staffPermissions, ({ many }) => ({
|
||||||
|
rolePermissions: many(staffRolePermissions),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const staffRolePermissionsRelations = relations(staffRolePermissions, ({ one }) => ({
|
||||||
|
role: one(staffRoles, { fields: [staffRolePermissions.staffRoleId], references: [staffRoles.id] }),
|
||||||
|
permission: one(staffPermissions, { fields: [staffRolePermissions.staffPermissionId], references: [staffPermissions.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const userIncidentsRelations = relations(userIncidents, ({ one }) => ({
|
||||||
|
user: one(users, { fields: [userIncidents.userId], references: [users.id] }),
|
||||||
|
order: one(orders, { fields: [userIncidents.orderId], references: [orders.id] }),
|
||||||
|
addedBy: one(staffUsers, { fields: [userIncidents.addedBy], references: [staffUsers.id] }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const productAvailabilitySchedulesRelations = relations(productAvailabilitySchedules, ({}) => ({
|
||||||
|
}));
|
||||||
153
apps/db-helper-postgres/src/db/seed.ts
Normal file
153
apps/db-helper-postgres/src/db/seed.ts
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
import { eq } from 'drizzle-orm'
|
||||||
|
|
||||||
|
import { CONST_KEYS } from '../../../backend/src/lib/const-keys'
|
||||||
|
import { deliveryCharge, minOrderValue } from '../../../backend/src/lib/env-exporter'
|
||||||
|
|
||||||
|
import { db } from './db_index'
|
||||||
|
import { keyValStore, staffPermissions, staffRolePermissions, staffRoles, units } from './schema'
|
||||||
|
|
||||||
|
export async function seed() {
|
||||||
|
console.log('Seeding database...')
|
||||||
|
|
||||||
|
const unitsToSeed = [
|
||||||
|
{ shortNotation: 'Kg', fullName: 'Kilogram' },
|
||||||
|
{ shortNotation: 'L', fullName: 'Litre' },
|
||||||
|
{ shortNotation: 'Dz', fullName: 'Dozen' },
|
||||||
|
{ shortNotation: 'Pc', fullName: 'Unit Piece' },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const unit of unitsToSeed) {
|
||||||
|
const existingUnit = await db.query.units.findFirst({
|
||||||
|
where: eq(units.shortNotation, unit.shortNotation),
|
||||||
|
})
|
||||||
|
if (!existingUnit) {
|
||||||
|
await db.insert(units).values(unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rolesToSeed = ['super_admin', 'admin', 'marketer', 'delivery_staff'] as const
|
||||||
|
|
||||||
|
for (const roleName of rolesToSeed) {
|
||||||
|
const existingRole = await db.query.staffRoles.findFirst({
|
||||||
|
where: eq(staffRoles.roleName, roleName),
|
||||||
|
})
|
||||||
|
if (!existingRole) {
|
||||||
|
await db.insert(staffRoles).values({ roleName })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionsToSeed = ['crud_product', 'make_coupon', 'crud_staff_users'] as const
|
||||||
|
|
||||||
|
for (const permissionName of permissionsToSeed) {
|
||||||
|
const existingPermission = await db.query.staffPermissions.findFirst({
|
||||||
|
where: eq(staffPermissions.permissionName, permissionName),
|
||||||
|
})
|
||||||
|
if (!existingPermission) {
|
||||||
|
await db.insert(staffPermissions).values({ permissionName })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.transaction(async (tx) => {
|
||||||
|
const superAdminRole = await tx.query.staffRoles.findFirst({
|
||||||
|
where: eq(staffRoles.roleName, 'super_admin'),
|
||||||
|
})
|
||||||
|
const adminRole = await tx.query.staffRoles.findFirst({
|
||||||
|
where: eq(staffRoles.roleName, 'admin'),
|
||||||
|
})
|
||||||
|
const marketerRole = await tx.query.staffRoles.findFirst({
|
||||||
|
where: eq(staffRoles.roleName, 'marketer'),
|
||||||
|
})
|
||||||
|
|
||||||
|
const crudProductPerm = await tx.query.staffPermissions.findFirst({
|
||||||
|
where: eq(staffPermissions.permissionName, 'crud_product'),
|
||||||
|
})
|
||||||
|
const makeCouponPerm = await tx.query.staffPermissions.findFirst({
|
||||||
|
where: eq(staffPermissions.permissionName, 'make_coupon'),
|
||||||
|
})
|
||||||
|
const crudStaffUsersPerm = await tx.query.staffPermissions.findFirst({
|
||||||
|
where: eq(staffPermissions.permissionName, 'crud_staff_users'),
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[crudProductPerm, makeCouponPerm, crudStaffUsersPerm].map(async (perm) => {
|
||||||
|
if (!superAdminRole || !perm) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingSuperAdminPerm = await tx.query.staffRolePermissions.findFirst({
|
||||||
|
where: eq(staffRolePermissions.staffRoleId, superAdminRole.id)
|
||||||
|
&& eq(staffRolePermissions.staffPermissionId, perm.id),
|
||||||
|
})
|
||||||
|
if (!existingSuperAdminPerm) {
|
||||||
|
await tx.insert(staffRolePermissions).values({
|
||||||
|
staffRoleId: superAdminRole.id,
|
||||||
|
staffPermissionId: perm.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[crudProductPerm, makeCouponPerm].map(async (perm) => {
|
||||||
|
if (!adminRole || !perm) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingAdminPerm = await tx.query.staffRolePermissions.findFirst({
|
||||||
|
where: eq(staffRolePermissions.staffRoleId, adminRole.id)
|
||||||
|
&& eq(staffRolePermissions.staffPermissionId, perm.id),
|
||||||
|
})
|
||||||
|
if (!existingAdminPerm) {
|
||||||
|
await tx.insert(staffRolePermissions).values({
|
||||||
|
staffRoleId: adminRole.id,
|
||||||
|
staffPermissionId: perm.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
if (marketerRole && makeCouponPerm) {
|
||||||
|
const existingMarketerCoupon = await tx.query.staffRolePermissions.findFirst({
|
||||||
|
where: eq(staffRolePermissions.staffRoleId, marketerRole.id)
|
||||||
|
&& eq(staffRolePermissions.staffPermissionId, makeCouponPerm.id),
|
||||||
|
})
|
||||||
|
if (!existingMarketerCoupon) {
|
||||||
|
await tx.insert(staffRolePermissions).values({
|
||||||
|
staffRoleId: marketerRole.id,
|
||||||
|
staffPermissionId: makeCouponPerm.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const constantsToSeed = [
|
||||||
|
{ key: CONST_KEYS.readableOrderId, value: 0 },
|
||||||
|
{ key: CONST_KEYS.minRegularOrderValue, value: minOrderValue },
|
||||||
|
{ key: CONST_KEYS.freeDeliveryThreshold, value: minOrderValue },
|
||||||
|
{ key: CONST_KEYS.deliveryCharge, value: deliveryCharge },
|
||||||
|
{ key: CONST_KEYS.flashFreeDeliveryThreshold, value: 500 },
|
||||||
|
{ key: CONST_KEYS.flashDeliveryCharge, value: 69 },
|
||||||
|
{ key: CONST_KEYS.popularItems, value: [] },
|
||||||
|
{ key: CONST_KEYS.allItemsOrder, value: [] },
|
||||||
|
{ key: CONST_KEYS.versionNum, value: '1.1.0' },
|
||||||
|
{ key: CONST_KEYS.playStoreUrl, value: 'https://play.google.com/store/apps/details?id=in.freshyo.app' },
|
||||||
|
{ key: CONST_KEYS.appStoreUrl, value: 'https://apps.apple.com/in/app/freshyo/id6756889077' },
|
||||||
|
{ key: CONST_KEYS.isFlashDeliveryEnabled, value: false },
|
||||||
|
{ key: CONST_KEYS.supportMobile, value: '8688182552' },
|
||||||
|
{ key: CONST_KEYS.supportEmail, value: 'qushammohd@gmail.com' },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const constant of constantsToSeed) {
|
||||||
|
const existing = await db.query.keyValStore.findFirst({
|
||||||
|
where: eq(keyValStore.key, constant.key),
|
||||||
|
})
|
||||||
|
if (!existing) {
|
||||||
|
await db.insert(keyValStore).values({
|
||||||
|
key: constant.key,
|
||||||
|
value: constant.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Seeding completed.')
|
||||||
|
}
|
||||||
47
apps/db-helper-postgres/src/db/types.ts
Normal file
47
apps/db-helper-postgres/src/db/types.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import type { InferSelectModel } from 'drizzle-orm'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
users,
|
||||||
|
addresses,
|
||||||
|
units,
|
||||||
|
productInfo,
|
||||||
|
deliverySlotInfo,
|
||||||
|
productSlots,
|
||||||
|
specialDeals,
|
||||||
|
orders,
|
||||||
|
orderItems,
|
||||||
|
payments,
|
||||||
|
notifications,
|
||||||
|
productCategories,
|
||||||
|
cartItems,
|
||||||
|
coupons,
|
||||||
|
} from './schema'
|
||||||
|
|
||||||
|
export type User = InferSelectModel<typeof users>
|
||||||
|
export type Address = InferSelectModel<typeof addresses>
|
||||||
|
export type Unit = InferSelectModel<typeof units>
|
||||||
|
export type ProductInfo = InferSelectModel<typeof productInfo>
|
||||||
|
export type DeliverySlotInfo = InferSelectModel<typeof deliverySlotInfo>
|
||||||
|
export type ProductSlot = InferSelectModel<typeof productSlots>
|
||||||
|
export type SpecialDeal = InferSelectModel<typeof specialDeals>
|
||||||
|
export type Order = InferSelectModel<typeof orders>
|
||||||
|
export type OrderItem = InferSelectModel<typeof orderItems>
|
||||||
|
export type Payment = InferSelectModel<typeof payments>
|
||||||
|
export type Notification = InferSelectModel<typeof notifications>
|
||||||
|
export type ProductCategory = InferSelectModel<typeof productCategories>
|
||||||
|
export type CartItem = InferSelectModel<typeof cartItems>
|
||||||
|
export type Coupon = InferSelectModel<typeof coupons>
|
||||||
|
|
||||||
|
export type ProductWithUnit = ProductInfo & {
|
||||||
|
unit: Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OrderWithItems = Order & {
|
||||||
|
items: (OrderItem & { product: ProductInfo })[]
|
||||||
|
address: Address
|
||||||
|
slot: DeliverySlotInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CartItemWithProduct = CartItem & {
|
||||||
|
product: ProductInfo
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import * as cron from 'node-cron';
|
import * as cron from 'node-cron';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { productInfo, productAvailabilitySchedules } from '@/src/db/schema'
|
import { productInfo, productAvailabilitySchedules } from '../db/schema'
|
||||||
import { inArray } from 'drizzle-orm';
|
import { inArray } from 'drizzle-orm';
|
||||||
import { initializeAllStores } from '../stores/store-initializer';
|
import { initializeAllStores } from '../stores/store-initializer';
|
||||||
|
|
||||||
|
|
@ -5,8 +5,8 @@ import { scaffoldStores } from '@/src/trpc/apis/user-apis/apis/stores'
|
||||||
import { scaffoldSlotsWithProducts } from '@/src/trpc/apis/user-apis/apis/slots'
|
import { scaffoldSlotsWithProducts } from '@/src/trpc/apis/user-apis/apis/slots'
|
||||||
import { scaffoldBanners } from '@/src/trpc/apis/user-apis/apis/banners'
|
import { scaffoldBanners } from '@/src/trpc/apis/user-apis/apis/banners'
|
||||||
import { scaffoldStoreWithProducts } from '@/src/trpc/apis/user-apis/apis/stores'
|
import { scaffoldStoreWithProducts } from '@/src/trpc/apis/user-apis/apis/stores'
|
||||||
import { storeInfo } from '@/src/db/schema'
|
import { storeInfo } from '../db/schema'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { imageUploadS3 } from '@/src/lib/s3-client'
|
import { imageUploadS3 } from '@/src/lib/s3-client'
|
||||||
import { apiCacheKey, cloudflareApiToken, cloudflareZoneId, assetsDomain } from '@/src/lib/env-exporter'
|
import { apiCacheKey, cloudflareApiToken, cloudflareZoneId, assetsDomain } from '@/src/lib/env-exporter'
|
||||||
import { CACHE_FILENAMES } from '@packages/shared'
|
import { CACHE_FILENAMES } from '@packages/shared'
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { keyValStore } from '@/src/db/schema'
|
import { keyValStore } from '../db/schema'
|
||||||
import redisClient from '@/src/lib/redis-client'
|
import redisClient from '@/src/lib/redis-client'
|
||||||
import { CONST_KEYS, CONST_KEYS_ARRAY, type ConstKey } from '@/src/lib/const-keys'
|
import { CONST_KEYS, CONST_KEYS_ARRAY, type ConstKey } from '@/src/lib/const-keys'
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { orders, orderItems, orderStatus, payments, refunds, couponUsage, complaints } from '@/src/db/schema'
|
import { orders, orderItems, orderStatus, payments, refunds, couponUsage, complaints } from '../db/schema'
|
||||||
import { eq, inArray } from 'drizzle-orm';
|
import { eq, inArray } from 'drizzle-orm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { productInfo, productAvailabilitySchedules } from '@/src/db/schema'
|
import { productInfo, productAvailabilitySchedules } from '../db/schema'
|
||||||
import { eq, inArray } from 'drizzle-orm';
|
import { eq, inArray } from 'drizzle-orm';
|
||||||
import { initializeAllStores } from '@/src/stores/store-initializer';
|
import { initializeAllStores } from '@/src/stores/store-initializer';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Queue, Worker } from 'bullmq';
|
import { Queue, Worker } from 'bullmq';
|
||||||
import { Expo } from 'expo-server-sdk';
|
import { Expo } from 'expo-server-sdk';
|
||||||
import { redisUrl } from '@/src/lib/env-exporter'
|
import { redisUrl } from '@/src/lib/env-exporter'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client'
|
import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client'
|
||||||
import {
|
import {
|
||||||
NOTIFS_QUEUE,
|
NOTIFS_QUEUE,
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { orders, orderStatus } from '@/src/db/schema'
|
import { orders, orderStatus } from '../db/schema'
|
||||||
import redisClient from '@/src/lib/redis-client'
|
import redisClient from '@/src/lib/redis-client'
|
||||||
import { sendTelegramMessage } from '@/src/lib/telegram-service'
|
import { sendTelegramMessage } from '@/src/lib/telegram-service'
|
||||||
import { inArray, eq } from 'drizzle-orm';
|
import { inArray, eq } from 'drizzle-orm';
|
||||||
23
apps/db-helper-postgres/src/lib/upload-url.ts
Normal file
23
apps/db-helper-postgres/src/lib/upload-url.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { and, eq } from 'drizzle-orm'
|
||||||
|
|
||||||
|
import { db } from '../db/db_index'
|
||||||
|
import { uploadUrlStatus } from '../db/schema'
|
||||||
|
|
||||||
|
export const createUploadUrlStatus = async (key: string): Promise<void> => {
|
||||||
|
await db.insert(uploadUrlStatus).values({
|
||||||
|
key,
|
||||||
|
status: 'pending',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const claimUploadUrlStatus = async (key: string): Promise<void> => {
|
||||||
|
const result = await db
|
||||||
|
.update(uploadUrlStatus)
|
||||||
|
.set({ status: 'claimed' })
|
||||||
|
.where(and(eq(uploadUrlStatus.key, key), eq(uploadUrlStatus.status, 'pending')))
|
||||||
|
.returning()
|
||||||
|
|
||||||
|
if (result.length === 0) {
|
||||||
|
throw new Error('Upload URL not found or already claimed')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createMiddleware } from 'hono/factory'
|
import { createMiddleware } from 'hono/factory'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { staffUsers, userDetails } from '@/src/db/schema'
|
import { staffUsers, userDetails } from '../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { ApiError } from '@/src/lib/api-error'
|
import { ApiError } from '@/src/lib/api-error'
|
||||||
import { verifyToken, UserJWTPayload, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
import { verifyToken, UserJWTPayload, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createMiddleware } from 'hono/factory'
|
import { createMiddleware } from 'hono/factory'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { staffUsers } from '@/src/db/schema'
|
import { staffUsers } from '../db/schema'
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import { ApiError } from '@/src/lib/api-error'
|
import { ApiError } from '@/src/lib/api-error'
|
||||||
import { verifyToken, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
import { verifyToken, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productReviews, users } from '@/src/db/schema'
|
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productReviews, users } from '../../db/schema'
|
||||||
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -55,8 +55,8 @@ export async function getProductDeliverySlots(productId: number) {
|
||||||
and(
|
and(
|
||||||
eq(productSlots.productId, productId),
|
eq(productSlots.productId, productId),
|
||||||
eq(deliverySlotInfo.isActive, true),
|
eq(deliverySlotInfo.isActive, true),
|
||||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`),
|
gt(deliverySlotInfo.deliveryTime, new Date()),
|
||||||
gt(deliverySlotInfo.freezeTime, sql`NOW()`)
|
gt(deliverySlotInfo.freezeTime, new Date())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.orderBy(deliverySlotInfo.deliveryTime)
|
.orderBy(deliverySlotInfo.deliveryTime)
|
||||||
|
|
@ -76,7 +76,7 @@ export async function getProductSpecialDeals(productId: number) {
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
eq(specialDeals.productId, productId),
|
eq(specialDeals.productId, productId),
|
||||||
gt(specialDeals.validTill, sql`NOW()`)
|
gt(specialDeals.validTill, new Date())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.orderBy(specialDeals.quantity)
|
.orderBy(specialDeals.quantity)
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// import redisClient from '@/src/stores/redis-client';
|
// import redisClient from '@/src/stores/redis-client';
|
||||||
import redisClient from '@/src/lib/redis-client';
|
import redisClient from '@/src/lib/redis-client';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { homeBanners } from '@/src/db/schema'
|
import { homeBanners } from '../db/schema'
|
||||||
import { isNotNull, asc } from 'drizzle-orm';
|
import { isNotNull, asc } from 'drizzle-orm';
|
||||||
import { scaffoldAssetUrl } from '@/src/lib/s3-client';
|
import { scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// import redisClient from '@/src/stores/redis-client';
|
// import redisClient from '@/src/stores/redis-client';
|
||||||
import redisClient from '@/src/lib/redis-client';
|
import redisClient from '@/src/lib/redis-client';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '@/src/db/schema'
|
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '../db/schema'
|
||||||
import { eq, and, gt, sql } from 'drizzle-orm';
|
import { eq, and, gt, sql } from 'drizzle-orm';
|
||||||
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ export async function initializeProducts(): Promise<void> {
|
||||||
and(
|
and(
|
||||||
eq(deliverySlotInfo.isActive, true),
|
eq(deliverySlotInfo.isActive, true),
|
||||||
eq(deliverySlotInfo.isCapacityFull, false),
|
eq(deliverySlotInfo.isCapacityFull, false),
|
||||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`)
|
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const deliverySlotsMap = new Map<number, typeof allDeliverySlots>();
|
const deliverySlotsMap = new Map<number, typeof allDeliverySlots>();
|
||||||
|
|
@ -90,7 +90,7 @@ export async function initializeProducts(): Promise<void> {
|
||||||
validTill: specialDeals.validTill,
|
validTill: specialDeals.validTill,
|
||||||
})
|
})
|
||||||
.from(specialDeals)
|
.from(specialDeals)
|
||||||
.where(gt(specialDeals.validTill, sql`NOW()`));
|
.where(gt(specialDeals.validTill, new Date()));
|
||||||
const specialDealsMap = new Map<number, typeof allSpecialDeals>();
|
const specialDealsMap = new Map<number, typeof allSpecialDeals>();
|
||||||
for (const deal of allSpecialDeals) {
|
for (const deal of allSpecialDeals) {
|
||||||
if (!specialDealsMap.has(deal.productId)) specialDealsMap.set(deal.productId, []);
|
if (!specialDealsMap.has(deal.productId)) specialDealsMap.set(deal.productId, []);
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// import redisClient from '@/src/stores/redis-client';
|
// import redisClient from '@/src/stores/redis-client';
|
||||||
import redisClient from '@/src/lib/redis-client';
|
import redisClient from '@/src/lib/redis-client';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { productTagInfo, productTags } from '@/src/db/schema'
|
import { productTagInfo, productTags } from '../db/schema'
|
||||||
import { eq, inArray } from 'drizzle-orm';
|
import { eq, inArray } from 'drizzle-orm';
|
||||||
import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client';
|
import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client';
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import redisClient from '@/src/lib/redis-client';
|
import redisClient from '@/src/lib/redis-client';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { deliverySlotInfo, productSlots, productInfo, units } from '@/src/db/schema'
|
import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema'
|
||||||
import { eq, and, gt, asc } from 'drizzle-orm';
|
import { eq, and, gt, asc } from 'drizzle-orm';
|
||||||
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import redisClient from '@/src/lib/redis-client';
|
import redisClient from '@/src/lib/redis-client';
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../db/db_index'
|
||||||
import { userIncidents } from '@/src/db/schema'
|
import { userIncidents } from '../db/schema'
|
||||||
import { eq, sum } from 'drizzle-orm';
|
import { eq, sum } from 'drizzle-orm';
|
||||||
|
|
||||||
export async function initializeUserNegativityStore(): Promise<void> {
|
export async function initializeUserNegativityStore(): Promise<void> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index'
|
import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index'
|
||||||
import { commonRouter } from '@/src/trpc/apis/common-apis/common'
|
import { commonRouter } from '@/src/trpc/apis/common-apis/common'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../../db/db_index'
|
||||||
import { keyValStore, productInfo, storeInfo } from '@/src/db/schema'
|
import { keyValStore, productInfo, storeInfo } from '../../../db/schema'
|
||||||
import * as turf from '@turf/turf';
|
import * as turf from '@turf/turf';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { mbnrGeoJson } from '@/src/lib/mbnr-geojson'
|
import { mbnrGeoJson } from '@/src/lib/mbnr-geojson'
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { router, publicProcedure } from '@/src/trpc/trpc-index'
|
import { router, publicProcedure } from '@/src/trpc/trpc-index'
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../../db/db_index'
|
||||||
import { productInfo, units, productSlots, deliverySlotInfo, storeInfo } from '@/src/db/schema'
|
import { productInfo, units, productSlots, deliverySlotInfo, storeInfo } from '../../../db/schema'
|
||||||
import { eq, gt, and, sql, inArray } from 'drizzle-orm';
|
import { eq, gt, and, sql, inArray } from 'drizzle-orm';
|
||||||
import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url } from '@/src/lib/s3-client'
|
import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url } from '@/src/lib/s3-client'
|
||||||
import { getAllProducts as getAllProductsFromCache } from '@/src/stores/product-store'
|
import { getAllProducts as getAllProductsFromCache } from '@/src/stores/product-store'
|
||||||
|
|
@ -16,7 +16,7 @@ export const getNextDeliveryDate = async (productId: number): Promise<Date | nul
|
||||||
eq(productSlots.productId, productId),
|
eq(productSlots.productId, productId),
|
||||||
eq(deliverySlotInfo.isActive, true),
|
eq(deliverySlotInfo.isActive, true),
|
||||||
eq(deliverySlotInfo.isCapacityFull, false),
|
eq(deliverySlotInfo.isCapacityFull, false),
|
||||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`)
|
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.orderBy(deliverySlotInfo.deliveryTime)
|
.orderBy(deliverySlotInfo.deliveryTime)
|
||||||
12
apps/db-helper-postgres/tsconfig.json
Normal file
12
apps/db-helper-postgres/tsconfig.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/src/db/*": ["./src/db/*"],
|
||||||
|
"@/src/*": ["../backend/src/*"],
|
||||||
|
"@/src/trpc/*": ["../backend/src/trpc/*"],
|
||||||
|
"@/src/lib/*": ["../backend/src/lib/*"],
|
||||||
|
"@/src/stores/*": ["../backend/src/stores/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,8 @@ import 'dotenv/config'
|
||||||
import { defineConfig } from 'drizzle-kit'
|
import { defineConfig } from 'drizzle-kit'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
out: './drizzle/sqlite',
|
out: './drizzle',
|
||||||
schema: './src/db/schema-sqlite.ts',
|
schema: './src/db/schema.ts',
|
||||||
dialect: 'sqlite',
|
dialect: 'sqlite',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: process.env.SQLITE_DB_PATH!,
|
url: process.env.SQLITE_DB_PATH!,
|
||||||
9
apps/db-helper-sqlite/package.json
Normal file
9
apps/db-helper-sqlite/package.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "db-helper-sqlite",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"drizzle-orm": "^0.45.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
102
apps/db-helper-sqlite/src/apis/common-apis/common-product.ts
Normal file
102
apps/db-helper-sqlite/src/apis/common-apis/common-product.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
import { and, eq, gt, inArray } from 'drizzle-orm'
|
||||||
|
|
||||||
|
import { db } from '../../db/db_index'
|
||||||
|
import { deliverySlotInfo, productInfo, productSlots, productTags, units } from '../../db/schema'
|
||||||
|
|
||||||
|
type ProductSummaryRow = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
shortDescription: string | null
|
||||||
|
price: string
|
||||||
|
marketPrice: string
|
||||||
|
images: string[]
|
||||||
|
isOutOfStock: boolean | null
|
||||||
|
unitShortNotation: string
|
||||||
|
productQuantity: number | null
|
||||||
|
nextDeliveryDate: Date | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizeImages = (images: string | null): string[] => {
|
||||||
|
if (!images) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(images)
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return parsed.filter((value) => typeof value === 'string')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to parse product images', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNextDeliveryDate = async (productId: number): Promise<Date | null> => {
|
||||||
|
const result = await db
|
||||||
|
.select({ deliveryTime: deliverySlotInfo.deliveryTime })
|
||||||
|
.from(productSlots)
|
||||||
|
.innerJoin(deliverySlotInfo, eq(productSlots.slotId, deliverySlotInfo.id))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(productSlots.productId, productId),
|
||||||
|
eq(deliverySlotInfo.isActive, true),
|
||||||
|
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderBy(deliverySlotInfo.deliveryTime)
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
return result[0]?.deliveryTime || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getProductsSummaryData = async (tagId?: number | null): Promise<ProductSummaryRow[]> => {
|
||||||
|
let productIds: number[] | null = null
|
||||||
|
|
||||||
|
if (tagId) {
|
||||||
|
const taggedProducts = await db
|
||||||
|
.select({ productId: productTags.productId })
|
||||||
|
.from(productTags)
|
||||||
|
.where(eq(productTags.tagId, tagId))
|
||||||
|
|
||||||
|
productIds = taggedProducts.map((taggedProduct) => taggedProduct.productId)
|
||||||
|
|
||||||
|
if (productIds.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereCondition = productIds && productIds.length > 0
|
||||||
|
? inArray(productInfo.id, productIds)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const productsWithUnits = await db
|
||||||
|
.select({
|
||||||
|
id: productInfo.id,
|
||||||
|
name: productInfo.name,
|
||||||
|
shortDescription: productInfo.shortDescription,
|
||||||
|
price: productInfo.price,
|
||||||
|
marketPrice: productInfo.marketPrice,
|
||||||
|
images: productInfo.images,
|
||||||
|
isOutOfStock: productInfo.isOutOfStock,
|
||||||
|
unitShortNotation: units.shortNotation,
|
||||||
|
productQuantity: productInfo.productQuantity,
|
||||||
|
})
|
||||||
|
.from(productInfo)
|
||||||
|
.innerJoin(units, eq(productInfo.unitId, units.id))
|
||||||
|
.where(whereCondition)
|
||||||
|
|
||||||
|
const productsWithDelivery = await Promise.all(
|
||||||
|
productsWithUnits.map(async (product) => {
|
||||||
|
const nextDeliveryDate = await getNextDeliveryDate(product.id)
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
images: normalizeImages(product.images),
|
||||||
|
nextDeliveryDate,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return productsWithDelivery
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { homeBanners } from '@/src/db/schema'
|
import { homeBanners } from '../../db/schema'
|
||||||
import { eq, desc } from 'drizzle-orm'
|
import { eq, desc } from 'drizzle-orm'
|
||||||
import { IBannerDbService, Banner, NewBanner } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
import { IBannerDbService, Banner, NewBanner } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class BannerDbService implements IBannerDbService {
|
export class BannerDbService implements IBannerDbService {
|
||||||
async getAllBanners(): Promise<Banner[]> {
|
async getAllBanners(): Promise<Banner[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { complaints, users } from '@/src/db/schema'
|
import { complaints, users } from '../../db/schema'
|
||||||
import { eq, desc, lt } from 'drizzle-orm'
|
import { eq, desc, lt } from 'drizzle-orm'
|
||||||
import { IComplaintDbService, Complaint, NewComplaint } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
import { IComplaintDbService, Complaint, NewComplaint } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/complaint-db-service.interface'
|
||||||
|
|
||||||
export class ComplaintDbService implements IComplaintDbService {
|
export class ComplaintDbService implements IComplaintDbService {
|
||||||
async getComplaints(
|
async getComplaints(
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { keyValStore } from '@/src/db/schema'
|
import { keyValStore } from '../../db/schema'
|
||||||
import { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
import { IConstantDbService, Constant, NewConstant } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class ConstantDbService implements IConstantDbService {
|
export class ConstantDbService implements IConstantDbService {
|
||||||
async getAllConstants(): Promise<Constant[]> {
|
async getAllConstants(): Promise<Constant[]> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '@/src/db/schema'
|
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '../../db/schema'
|
||||||
import { eq, and, like, or, inArray, lt, asc } from 'drizzle-orm'
|
import { eq, and, like, or, inArray, lt, asc } from 'drizzle-orm'
|
||||||
import { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
import { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
||||||
import { parseNumberArray, toJsonString } from '@/src/db/sqlite-casts'
|
import { parseNumberArray, toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class CouponDbService implements ICouponDbService {
|
export class CouponDbService implements ICouponDbService {
|
||||||
async createCoupon(data: NewCoupon): Promise<Coupon> {
|
async createCoupon(data: NewCoupon): Promise<Coupon> {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import {
|
import {
|
||||||
orders,
|
orders,
|
||||||
orderItems,
|
orderItems,
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
productInfo,
|
productInfo,
|
||||||
units,
|
units,
|
||||||
paymentInfoTable,
|
paymentInfoTable,
|
||||||
} from '@/src/db/schema'
|
} from '../../db/schema'
|
||||||
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
IOrderDbService,
|
IOrderDbService,
|
||||||
|
|
@ -26,7 +26,7 @@ import {
|
||||||
OrderWithRelations,
|
OrderWithRelations,
|
||||||
OrderWithStatus,
|
OrderWithStatus,
|
||||||
OrderWithCouponUsages,
|
OrderWithCouponUsages,
|
||||||
} from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
} from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/order-db-service.interface'
|
||||||
|
|
||||||
export class OrderDbService implements IOrderDbService {
|
export class OrderDbService implements IOrderDbService {
|
||||||
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '@/src/db/schema'
|
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '../../db/schema'
|
||||||
import { eq, and, inArray, desc, sql } from 'drizzle-orm'
|
import { eq, and, inArray, desc, sql } from 'drizzle-orm'
|
||||||
import { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
import { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class ProductDbService implements IProductDbService {
|
export class ProductDbService implements IProductDbService {
|
||||||
async getAllProducts(): Promise<Product[]> {
|
async getAllProducts(): Promise<Product[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { refunds, orders, orderStatus, payments } from '@/src/db/schema'
|
import { refunds, orders, orderStatus, payments } from '../../db/schema'
|
||||||
import { eq, and } from 'drizzle-orm'
|
import { eq, and } from 'drizzle-orm'
|
||||||
import { IRefundDbService, Refund, NewRefund } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
import { IRefundDbService, Refund, NewRefund } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/refund-db-service.interface'
|
||||||
|
|
||||||
export class RefundDbService implements IRefundDbService {
|
export class RefundDbService implements IRefundDbService {
|
||||||
async createRefund(data: NewRefund): Promise<Refund> {
|
async createRefund(data: NewRefund): Promise<Refund> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { productAvailabilitySchedules } from '@/src/db/schema'
|
import { productAvailabilitySchedules } from '../../db/schema'
|
||||||
import { eq, desc } from 'drizzle-orm'
|
import { eq, desc } from 'drizzle-orm'
|
||||||
import { IScheduleDbService, Schedule, NewSchedule } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
import { IScheduleDbService, Schedule, NewSchedule } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class ScheduleDbService implements IScheduleDbService {
|
export class ScheduleDbService implements IScheduleDbService {
|
||||||
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '@/src/db/schema'
|
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '../../db/schema'
|
||||||
import { eq, inArray, and, desc } from 'drizzle-orm'
|
import { eq, inArray, and, desc } from 'drizzle-orm'
|
||||||
import { ISlotDbService, Slot, NewSlot, ProductSlot, SlotWithRelations } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
import { ISlotDbService, Slot, NewSlot, ProductSlot, SlotWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
||||||
import { parseNumberArray, toJsonString } from '@/src/db/sqlite-casts'
|
import { parseNumberArray, toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class SlotDbService implements ISlotDbService {
|
export class SlotDbService implements ISlotDbService {
|
||||||
async getAllSlots(): Promise<SlotWithRelations[]> {
|
async getAllSlots(): Promise<SlotWithRelations[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { staffUsers, staffRoles, users, userDetails, orders } from '@/src/db/schema'
|
import { staffUsers, staffRoles, users, userDetails, orders } from '../../db/schema'
|
||||||
import { eq, or, like, and, lt, desc } from 'drizzle-orm'
|
import { eq, or, like, and, lt, desc } from 'drizzle-orm'
|
||||||
import { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole, StaffUserWithRole } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
import { IStaffUserDbService, StaffUser, NewStaffUser, StaffRole, StaffUserWithRole } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/staff-user-db-service.interface'
|
||||||
|
|
||||||
export class StaffUserDbService implements IStaffUserDbService {
|
export class StaffUserDbService implements IStaffUserDbService {
|
||||||
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { storeInfo, productInfo } from '@/src/db/schema'
|
import { storeInfo, productInfo } from '../../db/schema'
|
||||||
import { eq, inArray } from 'drizzle-orm'
|
import { eq, inArray } from 'drizzle-orm'
|
||||||
import { IStoreDbService, Store, NewStore } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
import { IStoreDbService, Store, NewStore } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/store-db-service.interface'
|
||||||
|
|
||||||
export class StoreDbService implements IStoreDbService {
|
export class StoreDbService implements IStoreDbService {
|
||||||
async getAllStores(): Promise<Store[]> {
|
async getAllStores(): Promise<Store[]> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { productTagInfo } from '@/src/db/schema'
|
import { productTagInfo } from '../../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { ITagDbService, Tag, NewTag } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
import { ITagDbService, Tag, NewTag } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class TagDbService implements ITagDbService {
|
export class TagDbService implements ITagDbService {
|
||||||
async getAllTags(): Promise<Tag[]> {
|
async getAllTags(): Promise<Tag[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '@/src/db/schema'
|
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '../../db/schema'
|
||||||
import { eq, desc, asc, count, max, inArray, and, like, gt } from 'drizzle-orm'
|
import { eq, desc, asc, count, max, inArray, and, like, gt } from 'drizzle-orm'
|
||||||
import { IUserDbService, User, NewUser, UserDetail } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
import { IUserDbService, User, NewUser, UserDetail } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/user-db-service.interface'
|
||||||
|
|
||||||
export class UserDbService implements IUserDbService {
|
export class UserDbService implements IUserDbService {
|
||||||
async getUserById(id: number): Promise<User | undefined> {
|
async getUserById(id: number): Promise<User | undefined> {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '@/src/db/schema'
|
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '../../db/schema'
|
||||||
import { eq, and, inArray, gt, asc, desc } from 'drizzle-orm'
|
import { eq, and, inArray, gt, asc, desc } from 'drizzle-orm'
|
||||||
import { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
import { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
||||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class VendorSnippetDbService implements IVendorSnippetDbService {
|
export class VendorSnippetDbService implements IVendorSnippetDbService {
|
||||||
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '@/src/db/schema'
|
import { addresses, orders, orderStatus, deliverySlotInfo } from '../../db/schema'
|
||||||
import { eq, and, gte } from 'drizzle-orm'
|
import { eq, and, gte } from 'drizzle-orm'
|
||||||
import { IUserAddressDbService, Address, NewAddress } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
import { IUserAddressDbService, Address, NewAddress } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-address-db-service.interface'
|
||||||
|
|
||||||
export class UserAddressDbService implements IUserAddressDbService {
|
export class UserAddressDbService implements IUserAddressDbService {
|
||||||
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { users, userCreds, userDetails, addresses, cartItems, complaints, couponApplicableUsers, couponUsage, notifCreds, notifications, orderItems, orderStatus, orders, payments, refunds, productReviews, reservedCoupons } from '@/src/db/schema'
|
import { users, userCreds, userDetails, addresses, cartItems, complaints, couponApplicableUsers, couponUsage, notifCreds, notifications, orderItems, orderStatus, orders, payments, refunds, productReviews, reservedCoupons } from '../../db/schema'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { IUserAuthDbService, User, UserCred, UserDetail } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
import { IUserAuthDbService, User, UserCred, UserDetail } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-auth-db-service.interface'
|
||||||
|
|
||||||
export class UserAuthDbService implements IUserAuthDbService {
|
export class UserAuthDbService implements IUserAuthDbService {
|
||||||
async getUserByEmail(email: string): Promise<User | undefined> {
|
async getUserByEmail(email: string): Promise<User | undefined> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { homeBanners } from '@/src/db/schema'
|
import { homeBanners } from '../../db/schema'
|
||||||
import { isNotNull, asc } from 'drizzle-orm'
|
import { isNotNull, asc } from 'drizzle-orm'
|
||||||
import { IUserBannerDbService, UserBanner } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
import { IUserBannerDbService, UserBanner } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-banner-db-service.interface'
|
||||||
|
|
||||||
export class UserBannerDbService implements IUserBannerDbService {
|
export class UserBannerDbService implements IUserBannerDbService {
|
||||||
async getActiveBanners(): Promise<UserBanner[]> {
|
async getActiveBanners(): Promise<UserBanner[]> {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { cartItems, productInfo, units } from '@/src/db/schema'
|
import { cartItems, productInfo, units } from '../../db/schema'
|
||||||
import { eq, and, sql } from 'drizzle-orm'
|
import { eq, and, sql } from 'drizzle-orm'
|
||||||
import { IUserCartDbService, CartItem } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
import { IUserCartDbService, CartItem } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-cart-db-service.interface'
|
||||||
|
|
||||||
export class UserCartDbService implements IUserCartDbService {
|
export class UserCartDbService implements IUserCartDbService {
|
||||||
async getCartItemsWithProducts(userId: number) {
|
async getCartItemsWithProducts(userId: number) {
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { complaints } from '@/src/db/schema'
|
import { complaints } from '../../db/schema'
|
||||||
import { eq, asc } from 'drizzle-orm'
|
import { eq, asc } from 'drizzle-orm'
|
||||||
import { IUserComplaintDbService } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
import { IUserComplaintDbService, NewComplaint } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-complaint-db-service.interface'
|
||||||
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
|
||||||
export class UserComplaintDbService implements IUserComplaintDbService {
|
export class UserComplaintDbService implements IUserComplaintDbService {
|
||||||
async getComplaintsByUserId(userId: number) {
|
async getComplaintsByUserId(userId: number) {
|
||||||
|
|
@ -20,8 +21,12 @@ export class UserComplaintDbService implements IUserComplaintDbService {
|
||||||
.orderBy(asc(complaints.createdAt))
|
.orderBy(asc(complaints.createdAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
async createComplaint(data: { userId: number; orderId?: number | null; complaintBody: string; images: string[] }) {
|
async createComplaint(data: NewComplaint) {
|
||||||
await db.insert(complaints).values(data)
|
const normalized = {
|
||||||
|
...data,
|
||||||
|
images: data.images ? toJsonString(data.images, '[]') : data.images,
|
||||||
|
}
|
||||||
|
await db.insert(complaints).values(normalized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '@/src/db/schema'
|
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '../../db/schema'
|
||||||
import { eq, and, or, gt, isNull } from 'drizzle-orm'
|
import { eq, and, or, gt, isNull } from 'drizzle-orm'
|
||||||
import { IUserCouponDbService, Coupon, ReservedCoupon, CouponWithRelations } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
import { IUserCouponDbService, Coupon, ReservedCoupon, CouponWithRelations } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-coupon-db-service.interface'
|
||||||
|
|
||||||
export class UserCouponDbService implements IUserCouponDbService {
|
export class UserCouponDbService implements IUserCouponDbService {
|
||||||
async getActiveCouponsForUser(userId: number): Promise<CouponWithRelations[]> {
|
async getActiveCouponsForUser(userId: number): Promise<CouponWithRelations[]> {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { db } from '@/src/db/db_index'
|
import { db } from '../../db/db_index'
|
||||||
import {
|
import {
|
||||||
orders,
|
orders,
|
||||||
orderItems,
|
orderItems,
|
||||||
|
|
@ -12,12 +12,12 @@ import {
|
||||||
refunds,
|
refunds,
|
||||||
units,
|
units,
|
||||||
userDetails,
|
userDetails,
|
||||||
} from '@/src/db/schema'
|
} from '../../db/schema'
|
||||||
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
IUserOrderDbService,
|
IUserOrderDbService,
|
||||||
Order,
|
Order,
|
||||||
} from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
} from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-order-db-service.interface'
|
||||||
|
|
||||||
export class UserOrderDbService implements IUserOrderDbService {
|
export class UserOrderDbService implements IUserOrderDbService {
|
||||||
async getUserDetailByUserId(userId: number) {
|
async getUserDetailByUserId(userId: number) {
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { db } from '@/src/db/db_index_sqlite'
|
import { db } from '../../db/db_index'
|
||||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '@/src/db/schema'
|
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '../../db/schema'
|
||||||
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
||||||
import { IUserProductDbService, Review } from '@/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
import { toJsonString } from '../../db/sqlite-casts'
|
||||||
|
import { IUserProductDbService, Review } from '../../../../backend/src/trpc/apis/user-apis/dataAccessors/interfaces/user-product-db-service.interface'
|
||||||
|
|
||||||
export class UserProductDbService implements IUserProductDbService {
|
export class UserProductDbService implements IUserProductDbService {
|
||||||
async getProductById(productId: number) {
|
async getProductById(productId: number) {
|
||||||
|
|
@ -103,7 +104,11 @@ export class UserProductDbService implements IUserProductDbService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async createReview(data: { userId: number; productId: number; reviewBody: string; ratings: number; imageUrls: string[] }): Promise<Review> {
|
async createReview(data: { userId: number; productId: number; reviewBody: string; ratings: number; imageUrls: string[] }): Promise<Review> {
|
||||||
const [newReview] = await db.insert(productReviews).values(data).returning()
|
const normalized = {
|
||||||
|
...data,
|
||||||
|
imageUrls: toJsonString(data.imageUrls, '[]'),
|
||||||
|
}
|
||||||
|
const [newReview] = await db.insert(productReviews).values(normalized).returning()
|
||||||
return newReview
|
return newReview
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue