freshyo/apps/db-helper-postgres/src/dataAccessors/admin-apis/coupon-queries.ts
2026-03-24 18:48:31 +05:30

191 lines
6.3 KiB
TypeScript

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 '../../../../backend/src/trpc/apis/admin-apis/dataAccessors/interfaces/coupon-db-service.interface'
export class CouponDbService implements ICouponDbService {
async createCoupon(data: NewCoupon): Promise<Coupon> {
const [coupon] = await db.insert(coupons).values(data).returning()
return coupon
}
async getCouponById(id: number): Promise<CouponWithRelations | undefined> {
const result = await db.query.coupons.findFirst({
where: eq(coupons.id, id),
with: {
creator: true,
applicableUsers: { with: { user: true } },
applicableProducts: { with: { product: true } },
},
})
if (!result) return undefined
return {
...result,
productIds: (result.productIds as number[] | null) || null,
} as CouponWithRelations
}
async getCouponByCode(code: string): Promise<Coupon | undefined> {
return db.query.coupons.findFirst({
where: eq(coupons.couponCode, code),
})
}
async getAllCoupons(options: { cursor?: number; limit: number; search?: string }): Promise<CouponWithRelations[]> {
const { cursor, limit, search } = options
let whereCondition = undefined
const conditions = []
if (cursor) {
conditions.push(lt(coupons.id, cursor))
}
if (search && search.trim()) {
conditions.push(like(coupons.couponCode, `%${search}%`))
}
if (conditions.length > 0) {
whereCondition = and(...conditions)
}
const result = await db.query.coupons.findMany({
where: whereCondition,
with: {
creator: true,
applicableUsers: { with: { user: true } },
applicableProducts: { with: { product: true } },
},
orderBy: (coupons, { desc }) => [desc(coupons.createdAt)],
limit: limit + 1,
})
return result.map((coupon) => ({
...coupon,
productIds: (coupon.productIds as number[] | null) || null,
})) as CouponWithRelations[]
}
async updateCoupon(id: number, data: Partial<NewCoupon>): Promise<Coupon> {
const [coupon] = await db.update(coupons).set(data).where(eq(coupons.id, id)).returning()
return coupon
}
async invalidateCoupon(id: number): Promise<Coupon> {
const [coupon] = await db.update(coupons).set({ isInvalidated: true }).where(eq(coupons.id, id)).returning()
return coupon
}
async addApplicableUsers(couponId: number, userIds: number[]): Promise<void> {
await db.insert(couponApplicableUsers).values(
userIds.map(userId => ({ couponId, userId }))
)
}
async addApplicableProducts(couponId: number, productIds: number[]): Promise<void> {
await db.insert(couponApplicableProducts).values(
productIds.map(productId => ({ couponId, productId }))
)
}
async removeAllApplicableUsers(couponId: number): Promise<void> {
await db.delete(couponApplicableUsers).where(eq(couponApplicableUsers.couponId, couponId))
}
async removeAllApplicableProducts(couponId: number): Promise<void> {
await db.delete(couponApplicableProducts).where(eq(couponApplicableProducts.couponId, couponId))
}
async countApplicableUsers(couponId: number): Promise<number> {
return db.$count(couponApplicableUsers, eq(couponApplicableUsers.couponId, couponId))
}
async createReservedCoupon(data: NewReservedCoupon): Promise<ReservedCoupon> {
const [coupon] = await db.insert(reservedCoupons).values(data).returning()
return coupon
}
async getReservedCoupons(options: { cursor?: number; limit: number; search?: string }): Promise<ReservedCoupon[]> {
const { cursor, limit, search } = options
let whereCondition = undefined
const conditions = []
if (cursor) {
conditions.push(lt(reservedCoupons.id, cursor))
}
if (search && search.trim()) {
conditions.push(or(
like(reservedCoupons.secretCode, `%${search}%`),
like(reservedCoupons.couponCode, `%${search}%`)
))
}
if (conditions.length > 0) {
whereCondition = and(...conditions)
}
return db.query.reservedCoupons.findMany({
where: whereCondition,
with: { redeemedUser: true, creator: true },
orderBy: (reservedCoupons, { desc }) => [desc(reservedCoupons.createdAt)],
limit: limit + 1,
})
}
async getUsersByIds(ids: number[]): Promise<Array<{ id: number; name: string | null; mobile: string | null }>> {
return db.query.users.findMany({
where: inArray(users.id, ids),
columns: { id: true, name: true, mobile: true },
})
}
async getUsersBySearch(search: string, limit: number, offset: number): Promise<Array<{ id: number; name: string | null; mobile: string | null }>> {
const whereCondition = or(
like(users.name, `%${search}%`),
like(users.mobile, `%${search}%`)
)
return db.query.users.findMany({
where: whereCondition,
columns: { id: true, name: true, mobile: true },
limit,
offset,
orderBy: (users, { asc }) => [asc(users.name)],
})
}
async createUser(data: Partial<typeof users.$inferInsert>): Promise<typeof users.$inferSelect> {
const [user] = await db.insert(users).values(data).returning()
return user
}
async getUserByMobile(mobile: string): Promise<typeof users.$inferSelect | undefined> {
return db.query.users.findFirst({
where: eq(users.mobile, mobile),
})
}
async getOrderByIdWithUserAndStatus(id: number): Promise<typeof orders.$inferSelect & { user?: typeof users.$inferSelect; orderStatus?: any[] } | undefined> {
return db.query.orders.findFirst({
where: eq(orders.id, id),
with: {
user: true,
orderStatus: true,
},
})
}
async updateOrderStatusRefundCoupon(orderId: number, couponId: number): Promise<void> {
await db.update(orderStatus)
.set({ refundCouponId: couponId })
.where(eq(orderStatus.orderId, orderId))
}
async withTransaction<T>(fn: (tx: any) => Promise<T>): Promise<T> {
return db.transaction(fn)
}
}
export const couponDbService: ICouponDbService = new CouponDbService()