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
|
||||
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
|
||||
SQLITE_DB_PATH='./sqlite.db'
|
||||
DB_DIALECT='sqlite'
|
||||
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
|
||||
|
||||
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
|
||||
PHONE_PE_CLIENT_VERSION=1
|
||||
PHONE_PE_CLIENT_SECRET=MTU1MmIzOTgtM2Q0Mi00N2M5LTkyMWUtNzBiMjdmYzVmZWUy
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
import 'dotenv/config';
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
import postgresConfig from '../db-helper-postgres/drizzle.config'
|
||||
import sqliteConfig from '../db-helper-sqlite/drizzle.config'
|
||||
|
||||
export default defineConfig({
|
||||
out: './drizzle',
|
||||
schema: './src/db/schema.ts',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
});
|
||||
export default process.env.DB_DIALECT === 'sqlite'
|
||||
? sqliteConfig
|
||||
: postgresConfig
|
||||
|
|
|
|||
|
|
@ -157,7 +157,6 @@ app.onError((err, c) => {
|
|||
return c.json({ message }, status)
|
||||
})
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Start server
|
||||
serve({
|
||||
fetch: app.fetch,
|
||||
|
|
@ -166,8 +165,3 @@ serve({
|
|||
})
|
||||
|
||||
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",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"migrate": "drizzle-kit generate --config drizzle.config.postgres.ts",
|
||||
"migrate:pg": "drizzle-kit generate --config drizzle.config.postgres.ts",
|
||||
"migrate:sqlite": "drizzle-kit generate --config drizzle.config.sqlite.ts",
|
||||
"generate:pg": "bunx drizzle-kit generate --config drizzle.config.postgres.ts",
|
||||
"generate:sqlite": "bunx drizzle-kit generate --config drizzle.config.sqlite.ts",
|
||||
"migrate": "drizzle-kit generate --config ../db-helper-postgres/drizzle.config.ts",
|
||||
"migrate:pg": "drizzle-kit generate --config ../db-helper-postgres/drizzle.config.ts",
|
||||
"migrate:sqlite": "drizzle-kit generate --config ../db-helper-sqlite/drizzle.config.ts",
|
||||
"generate:pg": "bunx drizzle-kit generate --config ../db-helper-postgres/drizzle.config.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",
|
||||
"build2": "rimraf ./dist && tsc",
|
||||
"db:push": "drizzle-kit push --config drizzle.config.postgres.ts",
|
||||
"db:push:pg": "drizzle-kit push --config drizzle.config.postgres.ts",
|
||||
"db:push:sqlite": "drizzle-kit push --config drizzle.config.sqlite.ts",
|
||||
"db:push": "drizzle-kit push --config ../db-helper-postgres/drizzle.config.ts",
|
||||
"db:push:pg": "drizzle-kit push --config ../db-helper-postgres/drizzle.config.ts",
|
||||
"db:push:sqlite": "drizzle-kit push --config ../db-helper-sqlite/drizzle.config.ts",
|
||||
"db:seed": "tsx src/db/seed.ts",
|
||||
"dev:express": "bun --watch index-express.ts",
|
||||
"dev:hono": "bun --watch index.ts",
|
||||
|
|
@ -46,7 +46,6 @@
|
|||
"jose": "^5.10.0",
|
||||
"node-cron": "^4.2.1",
|
||||
"pg": "^8.16.3",
|
||||
"razorpay": "^2.9.6",
|
||||
"redis": "^5.9.0",
|
||||
"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 { db } from "@/src/db/db_index"
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, productTags } from "@/src/db/schema"
|
||||
import { scaffoldAssetUrl } from "@/src/lib/s3-client"
|
||||
import { Context } from 'hono'
|
||||
|
||||
/**
|
||||
* Get next delivery date for a product
|
||||
*/
|
||||
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;
|
||||
};
|
||||
import { getProductsSummaryData } from '@/src/db/common-product'
|
||||
import { scaffoldAssetUrl } from '@/src/lib/s3-client'
|
||||
|
||||
/**
|
||||
* Get all products summary for dropdown
|
||||
*/
|
||||
export const getAllProductsSummary = async (c: Context) => {
|
||||
try {
|
||||
const tagId = c.req.query('tagId');
|
||||
const tagIdNum = tagId ? parseInt(tagId) : null;
|
||||
const tagId = c.req.query('tagId')
|
||||
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
|
||||
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 {
|
||||
const formattedProducts = productsWithUnits.map((product) => ({
|
||||
id: product.id,
|
||||
name: product.name,
|
||||
shortDescription: product.shortDescription,
|
||||
|
|
@ -88,18 +22,16 @@ export const getAllProductsSummary = async (c: Context) => {
|
|||
unit: product.unitShortNotation,
|
||||
productQuantity: product.productQuantity,
|
||||
isOutOfStock: product.isOutOfStock,
|
||||
nextDeliveryDate: nextDeliveryDate ? nextDeliveryDate.toISOString() : null,
|
||||
nextDeliveryDate: product.nextDeliveryDate ? product.nextDeliveryDate.toISOString() : null,
|
||||
images: scaffoldAssetUrl((product.images as string[]) || []),
|
||||
};
|
||||
})
|
||||
);
|
||||
}))
|
||||
|
||||
return c.json({
|
||||
products: formattedProducts,
|
||||
count: formattedProducts.length,
|
||||
});
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("Get products summary error:", error);
|
||||
return c.json({ error: "Failed to fetch products summary" }, 500);
|
||||
console.error('Get products summary error:', error)
|
||||
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 { migrate } from "drizzle-orm/node-postgres/migrator"
|
||||
import path from "path"
|
||||
import * as schema from "@/src/db/schema-postgres"
|
||||
import { db as postgresDb } from '@db-helper-postgres/db/db_index'
|
||||
import { db as sqliteDb } from '@db-helper-sqlite/db/db_index'
|
||||
|
||||
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 }
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
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, ({}) => ({
|
||||
}));
|
||||
export * from '@/db-helper-postgres/db/schema'
|
||||
|
|
|
|||
|
|
@ -1,735 +1 @@
|
|||
import {
|
||||
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),
|
||||
}))
|
||||
export * from '@/db-helper-sqlite/db/schema'
|
||||
|
|
|
|||
|
|
@ -1,138 +1,8 @@
|
|||
import { db } from "@/src/db/db_index"
|
||||
import { units, productInfo, deliverySlotInfo, productSlots, keyValStore, staffRoles, staffPermissions, staffRolePermissions } from "@/src/db/schema"
|
||||
import { eq } from "drizzle-orm";
|
||||
import { minOrderValue, deliveryCharge } from '@/src/lib/env-exporter'
|
||||
import { CONST_KEYS } from '@/src/lib/const-keys'
|
||||
import { seed as seedPostgres } from '@db-helper-postgres/db/seed'
|
||||
import { seed as seedSqlite } from '@db-helper-sqlite/db/seed'
|
||||
|
||||
export async function seed() {
|
||||
console.log("Seeding database...");
|
||||
const dialect = process.env.DB_DIALECT || DB_DIALECT_TYPE
|
||||
|
||||
// Seed units individually
|
||||
const unitsToSeed = [
|
||||
{ shortNotation: "Kg", fullName: "Kilogram" },
|
||||
{ shortNotation: "L", fullName: "Litre" },
|
||||
{ shortNotation: "Dz", fullName: "Dozen" },
|
||||
{ shortNotation: "Pc", fullName: "Unit Piece" },
|
||||
];
|
||||
const seedImpl = dialect === 'sqlite' ? seedSqlite : seedPostgres
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.");
|
||||
}
|
||||
export const seed = async () => seedImpl()
|
||||
|
|
|
|||
|
|
@ -1,34 +1 @@
|
|||
export const parseJsonValue = <T>(value: unknown, fallback: T): T => {
|
||||
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)
|
||||
}
|
||||
export * from '@/db-helper-sqlite/db/sqlite-casts'
|
||||
|
|
|
|||
|
|
@ -1,47 +1,58 @@
|
|||
import type { InferSelectModel } from "drizzle-orm";
|
||||
import type {
|
||||
users,
|
||||
addresses,
|
||||
units,
|
||||
productInfo,
|
||||
deliverySlotInfo,
|
||||
productSlots,
|
||||
specialDeals,
|
||||
orders,
|
||||
orderItems,
|
||||
payments,
|
||||
notifications,
|
||||
productCategories,
|
||||
cartItems,
|
||||
coupons,
|
||||
} from "@/src/db/schema";
|
||||
User as PostgresUser,
|
||||
Address as PostgresAddress,
|
||||
Unit as PostgresUnit,
|
||||
ProductInfo as PostgresProductInfo,
|
||||
DeliverySlotInfo as PostgresDeliverySlotInfo,
|
||||
ProductSlot as PostgresProductSlot,
|
||||
SpecialDeal as PostgresSpecialDeal,
|
||||
Order as PostgresOrder,
|
||||
OrderItem as PostgresOrderItem,
|
||||
Payment as PostgresPayment,
|
||||
Notification as PostgresNotification,
|
||||
ProductCategory as PostgresProductCategory,
|
||||
CartItem as PostgresCartItem,
|
||||
Coupon as PostgresCoupon,
|
||||
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>;
|
||||
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>;
|
||||
type UseSqlite = typeof DB_DIALECT_TYPE extends 'sqlite' ? true : false
|
||||
|
||||
// Combined types
|
||||
export type ProductWithUnit = ProductInfo & {
|
||||
unit: Unit;
|
||||
};
|
||||
|
||||
export type OrderWithItems = Order & {
|
||||
items: (OrderItem & { product: ProductInfo })[];
|
||||
address: Address;
|
||||
slot: DeliverySlotInfo;
|
||||
};
|
||||
|
||||
export type CartItemWithProduct = CartItem & {
|
||||
product: ProductInfo;
|
||||
};
|
||||
export type User = UseSqlite extends true ? SqliteUser : PostgresUser
|
||||
export type Address = UseSqlite extends true ? SqliteAddress : PostgresAddress
|
||||
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 ProductSlot = UseSqlite extends true ? SqliteProductSlot : PostgresProductSlot
|
||||
export type SpecialDeal = UseSqlite extends true ? SqliteSpecialDeal : PostgresSpecialDeal
|
||||
export type Order = UseSqlite extends true ? SqliteOrder : PostgresOrder
|
||||
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 ProductCategory = UseSqlite extends true ? SqliteProductCategory : PostgresProductCategory
|
||||
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 { db } from "@/src/db/db_index"
|
||||
import { deleteImageUtil, getOriginalUrlFromSignedUrl } from "@/src/lib/s3-client"
|
||||
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 {
|
||||
try {
|
||||
// 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
|
||||
// const comIndex = originalUrl.indexOf(".com/");
|
||||
const baseUrlIndex = originalUrl.indexOf(s3Url);
|
||||
const baseUrlIndex = originalUrl.indexOf(s3Url)
|
||||
|
||||
// If '.com/' is found, return everything after it
|
||||
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) {
|
||||
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;
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
export async function deleteS3Image(imageUrl: string) {
|
||||
try {
|
||||
|
||||
let key:string | null = '';
|
||||
let key: string | null = ''
|
||||
|
||||
if(imageUrl.includes(assetsDomain)) {
|
||||
if (imageUrl.includes(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
|
||||
const originalUrl = getOriginalUrlFromSignedUrl(imageUrl) || imageUrl;
|
||||
const originalUrl = getOriginalUrlFromSignedUrl(imageUrl) || imageUrl
|
||||
|
||||
key = extractS3Key(originalUrl || "");
|
||||
key = extractS3Key(originalUrl || '')
|
||||
}
|
||||
|
||||
else {
|
||||
key = imageUrl;
|
||||
key = imageUrl
|
||||
}
|
||||
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) {
|
||||
throw new Error("Failed to delete image from S3");
|
||||
throw new Error('Failed to delete image from S3')
|
||||
}
|
||||
} 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 { eq, inArray } from "drizzle-orm";
|
||||
|
||||
// Core notification dispatch methods (renamed for clarity)
|
||||
export async function dispatchBulkNotification({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { db } from "@/src/db/db_index"
|
||||
|
||||
/**
|
||||
* 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 signedUrlCache from "@/src/lib/signed-url-cache"
|
||||
import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName, assetsDomain } from "@/src/lib/env-exporter"
|
||||
import { db } from "@/src/db/db_index"; // Adjust path if needed
|
||||
import { uploadUrlStatus } from "@/src/db/schema"
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { claimUploadUrlStatus, createUploadUrlStatus } from '@/src/db/upload-url'
|
||||
|
||||
const s3Client = new S3Client({
|
||||
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> {
|
||||
try {
|
||||
// Insert record into upload_url_status
|
||||
await db.insert(uploadUrlStatus).values({
|
||||
key: key,
|
||||
status: 'pending',
|
||||
});
|
||||
await createUploadUrlStatus(key)
|
||||
|
||||
// Generate signed upload URL
|
||||
const command = new PutObjectCommand({
|
||||
|
|
@ -207,16 +202,7 @@ export async function claimUploadUrl(url: string): Promise<void> {
|
|||
semiKey = extractKeyFromPresignedUrl(url);
|
||||
else
|
||||
semiKey = url
|
||||
// Update status to 'claimed' if currently 'pending'
|
||||
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');
|
||||
}
|
||||
await claimUploadUrlStatus(semiKey)
|
||||
} catch (error) {
|
||||
console.error('Error claiming upload URL:', error);
|
||||
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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"@db-helper-postgres/*": ["../db-helper-postgres/src/*"],
|
||||
"@db-helper-sqlite/*": ["../db-helper-sqlite/src/*"],
|
||||
"shared-types": ["../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"]
|
||||
}
|
||||
|
||||
|
|
|
|||
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'
|
||||
|
||||
export default defineConfig({
|
||||
out: './drizzle/pg',
|
||||
schema: './src/db/schema-postgres.ts',
|
||||
out: './drizzle',
|
||||
schema: './src/db/schema.ts',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
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 { homeBanners } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { homeBanners } from '../../db/schema'
|
||||
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 {
|
||||
async getAllBanners(): Promise<Banner[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { complaints, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { complaints, users } from '../../db/schema'
|
||||
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 {
|
||||
async getComplaints(
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { keyValStore } from '@/src/db/schema'
|
||||
import { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||
import { db } from '../../db/db_index'
|
||||
import { keyValStore } from '../../db/schema'
|
||||
import { IConstantDbService, Constant, NewConstant } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||
|
||||
export class ConstantDbService implements IConstantDbService {
|
||||
async getAllConstants(): Promise<Constant[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '../../db/schema'
|
||||
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 {
|
||||
async createCoupon(data: NewCoupon): Promise<Coupon> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { db } from '../../db/db_index'
|
||||
import {
|
||||
orders,
|
||||
orderItems,
|
||||
|
|
@ -14,7 +14,7 @@ import {
|
|||
productInfo,
|
||||
units,
|
||||
paymentInfoTable,
|
||||
} from '@/src/db/schema'
|
||||
} from '../../db/schema'
|
||||
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
||||
import {
|
||||
IOrderDbService,
|
||||
|
|
@ -26,7 +26,7 @@ import {
|
|||
OrderWithRelations,
|
||||
OrderWithStatus,
|
||||
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 {
|
||||
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '../../db/schema'
|
||||
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 {
|
||||
async getAllProducts(): Promise<Product[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { refunds, orders, orderStatus, payments } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { refunds, orders, orderStatus, payments } from '../../db/schema'
|
||||
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 {
|
||||
async createRefund(data: NewRefund): Promise<Refund> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productAvailabilitySchedules } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productAvailabilitySchedules } from '../../db/schema'
|
||||
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 {
|
||||
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getAllSlots(): Promise<SlotWithRelations[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { staffUsers, staffRoles, users, userDetails, orders } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { staffUsers, staffRoles, users, userDetails, orders } from '../../db/schema'
|
||||
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 {
|
||||
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { storeInfo, productInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { storeInfo, productInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getAllStores(): Promise<Store[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productTagInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productTagInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getAllTags(): Promise<Tag[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
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 { 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 {
|
||||
async getUserById(id: number): Promise<User | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '../../db/schema'
|
||||
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 {
|
||||
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/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 { db } from '../../db/db_index'
|
||||
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 { 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 {
|
||||
async getUserByEmail(email: string): Promise<User | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { homeBanners } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { homeBanners } from '../../db/schema'
|
||||
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 {
|
||||
async getActiveBanners(): Promise<UserBanner[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { cartItems, productInfo, units } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { cartItems, productInfo, units } from '../../db/schema'
|
||||
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 {
|
||||
async getCartItemsWithProducts(userId: number) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { complaints } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { complaints } from '../../db/schema'
|
||||
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 {
|
||||
async getComplaintsByUserId(userId: number) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '../../db/schema'
|
||||
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 {
|
||||
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 {
|
||||
orders,
|
||||
orderItems,
|
||||
|
|
@ -12,12 +12,12 @@ import {
|
|||
refunds,
|
||||
units,
|
||||
userDetails,
|
||||
} from '@/src/db/schema'
|
||||
} from '../../db/schema'
|
||||
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
||||
import {
|
||||
IUserOrderDbService,
|
||||
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 {
|
||||
async getUserDetailByUserId(userId: number) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '../../db/schema'
|
||||
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 {
|
||||
async getProductById(productId: number) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { users, userDetails, userCreds, notifCreds, unloggedUserTokens } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { users, userDetails, userCreds, notifCreds, unloggedUserTokens } from '../../db/schema'
|
||||
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 {
|
||||
async getUserById(userId: number): Promise<User | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { deliverySlotInfo, productInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { deliverySlotInfo, productInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getActiveSlots(): Promise<Slot[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { storeInfo, productInfo, units } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { storeInfo, productInfo, units } from '../../db/schema'
|
||||
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 {
|
||||
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
|
||||
*/
|
||||
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { db } from './db_index'
|
||||
import {
|
||||
userDetails,
|
||||
productInfo,
|
||||
productTagInfo,
|
||||
complaints
|
||||
} from '@/src/db/schema';
|
||||
} from './schema';
|
||||
import { eq, not, isNull } from 'drizzle-orm';
|
||||
|
||||
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 { db } from '@/src/db/db_index'
|
||||
import { productInfo, productAvailabilitySchedules } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { productInfo, productAvailabilitySchedules } from '../db/schema'
|
||||
import { inArray } from 'drizzle-orm';
|
||||
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 { scaffoldBanners } from '@/src/trpc/apis/user-apis/apis/banners'
|
||||
import { scaffoldStoreWithProducts } from '@/src/trpc/apis/user-apis/apis/stores'
|
||||
import { storeInfo } from '@/src/db/schema'
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { storeInfo } from '../db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { imageUploadS3 } from '@/src/lib/s3-client'
|
||||
import { apiCacheKey, cloudflareApiToken, cloudflareZoneId, assetsDomain } from '@/src/lib/env-exporter'
|
||||
import { CACHE_FILENAMES } from '@packages/shared'
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { keyValStore } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { keyValStore } from '../db/schema'
|
||||
import redisClient from '@/src/lib/redis-client'
|
||||
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 { orders, orderItems, orderStatus, payments, refunds, couponUsage, complaints } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { orders, orderItems, orderStatus, payments, refunds, couponUsage, complaints } from '../db/schema'
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
|
||||
/**
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, productAvailabilitySchedules } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { productInfo, productAvailabilitySchedules } from '../db/schema'
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
import { initializeAllStores } from '@/src/stores/store-initializer';
|
||||
import dayjs from 'dayjs';
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { Queue, Worker } from 'bullmq';
|
||||
import { Expo } from 'expo-server-sdk';
|
||||
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 {
|
||||
NOTIFS_QUEUE,
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { orders, orderStatus } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { orders, orderStatus } from '../db/schema'
|
||||
import redisClient from '@/src/lib/redis-client'
|
||||
import { sendTelegramMessage } from '@/src/lib/telegram-service'
|
||||
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 { db } from '@/src/db/db_index'
|
||||
import { staffUsers, userDetails } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { staffUsers, userDetails } from '../db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { ApiError } from '@/src/lib/api-error'
|
||||
import { verifyToken, UserJWTPayload, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { createMiddleware } from 'hono/factory'
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { staffUsers } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { staffUsers } from '../db/schema'
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { ApiError } from '@/src/lib/api-error'
|
||||
import { verifyToken, StaffJWTPayload } from '@/src/lib/jwt-utils'
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productReviews, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productReviews, users } from '../../db/schema'
|
||||
import { eq, and, gt, sql, desc } from 'drizzle-orm'
|
||||
|
||||
/**
|
||||
|
|
@ -55,8 +55,8 @@ export async function getProductDeliverySlots(productId: number) {
|
|||
and(
|
||||
eq(productSlots.productId, productId),
|
||||
eq(deliverySlotInfo.isActive, true),
|
||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`),
|
||||
gt(deliverySlotInfo.freezeTime, sql`NOW()`)
|
||||
gt(deliverySlotInfo.deliveryTime, new Date()),
|
||||
gt(deliverySlotInfo.freezeTime, new Date())
|
||||
)
|
||||
)
|
||||
.orderBy(deliverySlotInfo.deliveryTime)
|
||||
|
|
@ -76,7 +76,7 @@ export async function getProductSpecialDeals(productId: number) {
|
|||
.where(
|
||||
and(
|
||||
eq(specialDeals.productId, productId),
|
||||
gt(specialDeals.validTill, sql`NOW()`)
|
||||
gt(specialDeals.validTill, new Date())
|
||||
)
|
||||
)
|
||||
.orderBy(specialDeals.quantity)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// import redisClient from '@/src/stores/redis-client';
|
||||
import redisClient from '@/src/lib/redis-client';
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { homeBanners } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { homeBanners } from '../db/schema'
|
||||
import { isNotNull, asc } from 'drizzle-orm';
|
||||
import { scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// import redisClient from '@/src/stores/redis-client';
|
||||
import redisClient from '@/src/lib/redis-client';
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '../db/schema'
|
||||
import { eq, and, gt, sql } from 'drizzle-orm';
|
||||
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ export async function initializeProducts(): Promise<void> {
|
|||
and(
|
||||
eq(deliverySlotInfo.isActive, true),
|
||||
eq(deliverySlotInfo.isCapacityFull, false),
|
||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`)
|
||||
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||
)
|
||||
);
|
||||
const deliverySlotsMap = new Map<number, typeof allDeliverySlots>();
|
||||
|
|
@ -90,7 +90,7 @@ export async function initializeProducts(): Promise<void> {
|
|||
validTill: specialDeals.validTill,
|
||||
})
|
||||
.from(specialDeals)
|
||||
.where(gt(specialDeals.validTill, sql`NOW()`));
|
||||
.where(gt(specialDeals.validTill, new Date()));
|
||||
const specialDealsMap = new Map<number, typeof allSpecialDeals>();
|
||||
for (const deal of allSpecialDeals) {
|
||||
if (!specialDealsMap.has(deal.productId)) specialDealsMap.set(deal.productId, []);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// import redisClient from '@/src/stores/redis-client';
|
||||
import redisClient from '@/src/lib/redis-client';
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { productTagInfo, productTags } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { productTagInfo, productTags } from '../db/schema'
|
||||
import { eq, inArray } from 'drizzle-orm';
|
||||
import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client';
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import redisClient from '@/src/lib/redis-client';
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { deliverySlotInfo, productSlots, productInfo, units } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema'
|
||||
import { eq, and, gt, asc } from 'drizzle-orm';
|
||||
import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '@/src/lib/s3-client';
|
||||
import dayjs from 'dayjs';
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import redisClient from '@/src/lib/redis-client';
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { userIncidents } from '@/src/db/schema'
|
||||
import { db } from '../db/db_index'
|
||||
import { userIncidents } from '../db/schema'
|
||||
import { eq, sum } from 'drizzle-orm';
|
||||
|
||||
export async function initializeUserNegativityStore(): Promise<void> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index'
|
||||
import { commonRouter } from '@/src/trpc/apis/common-apis/common'
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { keyValStore, productInfo, storeInfo } from '@/src/db/schema'
|
||||
import { db } from '../../../db/db_index'
|
||||
import { keyValStore, productInfo, storeInfo } from '../../../db/schema'
|
||||
import * as turf from '@turf/turf';
|
||||
import { z } from 'zod';
|
||||
import { mbnrGeoJson } from '@/src/lib/mbnr-geojson'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { router, publicProcedure } from '@/src/trpc/trpc-index'
|
||||
import { db } from '@/src/db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, storeInfo } from '@/src/db/schema'
|
||||
import { db } from '../../../db/db_index'
|
||||
import { productInfo, units, productSlots, deliverySlotInfo, storeInfo } from '../../../db/schema'
|
||||
import { eq, gt, and, sql, inArray } from 'drizzle-orm';
|
||||
import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url } from '@/src/lib/s3-client'
|
||||
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(deliverySlotInfo.isActive, true),
|
||||
eq(deliverySlotInfo.isCapacityFull, false),
|
||||
gt(deliverySlotInfo.deliveryTime, sql`NOW()`)
|
||||
gt(deliverySlotInfo.deliveryTime, new Date())
|
||||
)
|
||||
)
|
||||
.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'
|
||||
|
||||
export default defineConfig({
|
||||
out: './drizzle/sqlite',
|
||||
schema: './src/db/schema-sqlite.ts',
|
||||
out: './drizzle',
|
||||
schema: './src/db/schema.ts',
|
||||
dialect: 'sqlite',
|
||||
dbCredentials: {
|
||||
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 { homeBanners } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { homeBanners } from '../../db/schema'
|
||||
import { eq, desc } from 'drizzle-orm'
|
||||
import { IBannerDbService, Banner, NewBanner } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { IBannerDbService, Banner, NewBanner } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/banner-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class BannerDbService implements IBannerDbService {
|
||||
async getAllBanners(): Promise<Banner[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { complaints, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { complaints, users } from '../../db/schema'
|
||||
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 {
|
||||
async getComplaints(
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { keyValStore } from '@/src/db/schema'
|
||||
import { IConstantDbService, Constant, NewConstant } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { db } from '../../db/db_index'
|
||||
import { keyValStore } from '../../db/schema'
|
||||
import { IConstantDbService, Constant, NewConstant } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/constant-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class ConstantDbService implements IConstantDbService {
|
||||
async getAllConstants(): Promise<Constant[]> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { coupons, couponApplicableUsers, couponApplicableProducts, reservedCoupons, users, orders, orderStatus } from '../../db/schema'
|
||||
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 { parseNumberArray, toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { ICouponDbService, Coupon, NewCoupon, ReservedCoupon, NewReservedCoupon, CouponWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
|
||||
import { parseNumberArray, toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class CouponDbService implements ICouponDbService {
|
||||
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 {
|
||||
orders,
|
||||
orderItems,
|
||||
|
|
@ -14,7 +14,7 @@ import {
|
|||
productInfo,
|
||||
units,
|
||||
paymentInfoTable,
|
||||
} from '@/src/db/schema'
|
||||
} from '../../db/schema'
|
||||
import { eq, and, gte, lt, desc, inArray, SQL } from 'drizzle-orm'
|
||||
import {
|
||||
IOrderDbService,
|
||||
|
|
@ -26,7 +26,7 @@ import {
|
|||
OrderWithRelations,
|
||||
OrderWithStatus,
|
||||
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 {
|
||||
async updateOrderNotes(orderId: number, adminNotes: string | null): Promise<Order> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productInfo, units, specialDeals, productSlots, productTags, productReviews, productGroupInfo, productGroupMembership, users } from '../../db/schema'
|
||||
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 { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { IProductDbService, Product, NewProduct, ProductGroup, NewProductGroup } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/product-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class ProductDbService implements IProductDbService {
|
||||
async getAllProducts(): Promise<Product[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { refunds, orders, orderStatus, payments } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { refunds, orders, orderStatus, payments } from '../../db/schema'
|
||||
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 {
|
||||
async createRefund(data: NewRefund): Promise<Refund> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { productAvailabilitySchedules } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productAvailabilitySchedules } from '../../db/schema'
|
||||
import { eq, desc } from 'drizzle-orm'
|
||||
import { IScheduleDbService, Schedule, NewSchedule } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { IScheduleDbService, Schedule, NewSchedule } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/schedule-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class ScheduleDbService implements IScheduleDbService {
|
||||
async createSchedule(data: NewSchedule): Promise<Schedule> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { deliverySlotInfo, productSlots, vendorSnippets, productInfo, productGroupInfo } from '../../db/schema'
|
||||
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 { parseNumberArray, toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { ISlotDbService, Slot, NewSlot, ProductSlot, SlotWithRelations } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/slot-db-service.interface'
|
||||
import { parseNumberArray, toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class SlotDbService implements ISlotDbService {
|
||||
async getAllSlots(): Promise<SlotWithRelations[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { staffUsers, staffRoles, users, userDetails, orders } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { staffUsers, staffRoles, users, userDetails, orders } from '../../db/schema'
|
||||
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 {
|
||||
async getStaffUserByName(name: string): Promise<StaffUser | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { storeInfo, productInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { storeInfo, productInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getAllStores(): Promise<Store[]> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { productTagInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productTagInfo } from '../../db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { ITagDbService, Tag, NewTag } from '@/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
||||
import { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { ITagDbService, Tag, NewTag } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/tag-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class TagDbService implements ITagDbService {
|
||||
async getAllTags(): Promise<Tag[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { users, userDetails, orders, orderItems, orderStatus, complaints, notifCreds, unloggedUserTokens, userIncidents } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
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 { 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 {
|
||||
async getUserById(id: number): Promise<User | undefined> {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { vendorSnippets, deliverySlotInfo, orders, orderItems, productInfo } from '../../db/schema'
|
||||
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 { toJsonString } from '@/src/db/sqlite-casts'
|
||||
import { IVendorSnippetDbService, VendorSnippet, NewVendorSnippet } from '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/vendor-snippet-db-service.interface'
|
||||
import { toJsonString } from '../../db/sqlite-casts'
|
||||
|
||||
export class VendorSnippetDbService implements IVendorSnippetDbService {
|
||||
async createSnippet(data: NewVendorSnippet): Promise<VendorSnippet> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { addresses, orders, orderStatus, deliverySlotInfo } from '../../db/schema'
|
||||
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 {
|
||||
async getDefaultAddress(userId: number): Promise<Address | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { users, userCreds, userDetails, addresses, cartItems, complaints, couponApplicableUsers, couponUsage, notifCreds, notifications, orderItems, orderStatus, orders, payments, refunds, productReviews, reservedCoupons } from '@/src/db/schema'
|
||||
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 '../../db/schema'
|
||||
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 {
|
||||
async getUserByEmail(email: string): Promise<User | undefined> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { homeBanners } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { homeBanners } from '../../db/schema'
|
||||
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 {
|
||||
async getActiveBanners(): Promise<UserBanner[]> {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { cartItems, productInfo, units } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { cartItems, productInfo, units } from '../../db/schema'
|
||||
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 {
|
||||
async getCartItemsWithProducts(userId: number) {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { complaints } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { complaints } from '../../db/schema'
|
||||
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 {
|
||||
async getComplaintsByUserId(userId: number) {
|
||||
|
|
@ -20,8 +21,12 @@ export class UserComplaintDbService implements IUserComplaintDbService {
|
|||
.orderBy(asc(complaints.createdAt))
|
||||
}
|
||||
|
||||
async createComplaint(data: { userId: number; orderId?: number | null; complaintBody: string; images: string[] }) {
|
||||
await db.insert(complaints).values(data)
|
||||
async createComplaint(data: NewComplaint) {
|
||||
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 { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { coupons, couponUsage, couponApplicableUsers, couponApplicableProducts, reservedCoupons } from '../../db/schema'
|
||||
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 {
|
||||
async getActiveCouponsForUser(userId: number): Promise<CouponWithRelations[]> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { db } from '@/src/db/db_index'
|
||||
import { db } from '../../db/db_index'
|
||||
import {
|
||||
orders,
|
||||
orderItems,
|
||||
|
|
@ -12,12 +12,12 @@ import {
|
|||
refunds,
|
||||
units,
|
||||
userDetails,
|
||||
} from '@/src/db/schema'
|
||||
} from '../../db/schema'
|
||||
import { and, desc, eq, gte, inArray } from 'drizzle-orm'
|
||||
import {
|
||||
IUserOrderDbService,
|
||||
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 {
|
||||
async getUserDetailByUserId(userId: number) {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { db } from '@/src/db/db_index_sqlite'
|
||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '@/src/db/schema'
|
||||
import { db } from '../../db/db_index'
|
||||
import { productInfo, units, storeInfo, productSlots, deliverySlotInfo, specialDeals, productReviews, users } from '../../db/schema'
|
||||
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 {
|
||||
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> {
|
||||
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
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue