import { Inject, Injectable } from '@nestjs/common'; import { and, eq, ilike, or, sql } from 'drizzle-orm'; import { NodePgDatabase } from 'drizzle-orm/node-postgres/driver.js'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; import * as schema from '../drizzle/schema.js'; import { PG_CONNECTION } from '../drizzle/schema.js'; import { FileService } from '../file/file.service.js'; import { User } from '../models/db.model.js'; import { ListingCriteria } from '../models/main.model.js'; @Injectable() export class UserService { constructor( @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, @Inject(PG_CONNECTION) private conn: NodePgDatabase, private fileService: FileService, ) {} private getConditions(criteria: ListingCriteria): any[] { const conditions = []; if (criteria.state) { conditions.push(sql`EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`); } if (criteria.name) { conditions.push(or(ilike(schema.users.firstname, `%${criteria.name}%`), ilike(schema.users.lastname, `%${criteria.name}%`))); } return conditions; } async getUserByMail(email: string) { const users = (await this.conn .select() .from(schema.users) .where(sql`email = ${email}`)) as User[]; const user = users[0]; user.hasCompanyLogo = this.fileService.hasCompanyLogo(user.id); user.hasProfile = this.fileService.hasProfile(user.id); return user; } async getUserById(id: string) { const users = (await this.conn .select() .from(schema.users) .where(sql`id = ${id}`)) as User[]; const user = users[0]; user.hasCompanyLogo = this.fileService.hasCompanyLogo(id); user.hasProfile = this.fileService.hasProfile(id); return user; } async saveUser(user: any): Promise { if (user.id) { user.created = new Date(user.created); user.updated = new Date(); const [updateUser] = await this.conn.update(schema.users).set(user).where(eq(schema.users.id, user.id)).returning(); return updateUser as User; } else { user.created = new Date(); user.updated = new Date(); const [newUser] = await this.conn.insert(schema.users).values(user).returning(); return newUser as User; } } async findUser(criteria: ListingCriteria) { const start = criteria.start ? criteria.start : 0; const length = criteria.length ? criteria.length : 12; const conditions = this.getConditions(criteria); const [data, total] = await Promise.all([ this.conn .select() .from(schema.users) .where(and(...conditions)) .offset(start) .limit(length), this.conn .select({ count: sql`count(*)` }) .from(schema.users) .where(and(...conditions)) .then(result => Number(result[0].count)), ]); return { total, data }; } }