152 lines
4.9 KiB
TypeScript
152 lines
4.9 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { BaseTenantRepository, TenantContextService } from '@iconsulting/shared';
|
|
import { IUserContactRepository } from '../../../domain/repositories/user-contact.repository.interface';
|
|
import {
|
|
UserContactEntity,
|
|
ContactType,
|
|
NotificationType,
|
|
} from '../../../domain/entities/user-contact.entity';
|
|
import { UserContactORM } from '../../../infrastructure/database/postgres/entities/user-contact.orm';
|
|
|
|
@Injectable()
|
|
export class UserContactPostgresRepository
|
|
extends BaseTenantRepository<UserContactEntity, UserContactORM>
|
|
implements IUserContactRepository
|
|
{
|
|
constructor(
|
|
@InjectRepository(UserContactORM) repo: Repository<UserContactORM>,
|
|
tenantContext: TenantContextService,
|
|
) {
|
|
super(repo, tenantContext);
|
|
}
|
|
|
|
async save(contact: UserContactEntity): Promise<void> {
|
|
const orm = this.toORM(contact);
|
|
orm.tenantId = this.getTenantId();
|
|
await this.repo.save(orm);
|
|
}
|
|
|
|
async findById(id: string): Promise<UserContactEntity | null> {
|
|
const orm = await this.findOneWithTenant({ id } as any);
|
|
return orm ? this.toEntity(orm) : null;
|
|
}
|
|
|
|
async findByUserIdAndType(userId: string, type: ContactType): Promise<UserContactEntity | null> {
|
|
const orm = await this.findOneWithTenant({ userId, type } as any);
|
|
return orm ? this.toEntity(orm) : null;
|
|
}
|
|
|
|
async findByUserId(userId: string): Promise<UserContactEntity[]> {
|
|
const orms = await this.repo.find({
|
|
where: { userId, tenantId: this.getTenantId() } as any,
|
|
order: { createdAt: 'ASC' },
|
|
});
|
|
return orms.map(orm => this.toEntity(orm));
|
|
}
|
|
|
|
async findVerifiedByUserId(userId: string): Promise<UserContactEntity[]> {
|
|
const orms = await this.repo.find({
|
|
where: { userId, tenantId: this.getTenantId(), isVerified: true } as any,
|
|
order: { createdAt: 'ASC' },
|
|
});
|
|
return orms.map(orm => this.toEntity(orm));
|
|
}
|
|
|
|
async update(contact: UserContactEntity): Promise<void> {
|
|
const orm = this.toORM(contact);
|
|
orm.tenantId = this.getTenantId();
|
|
await this.repo.save(orm);
|
|
}
|
|
|
|
async delete(id: string): Promise<void> {
|
|
await this.repo.delete({ id, tenantId: this.getTenantId() } as any);
|
|
}
|
|
|
|
async findByNotificationType(
|
|
notificationType: NotificationType,
|
|
options?: { limit?: number; offset?: number },
|
|
): Promise<UserContactEntity[]> {
|
|
const query = this.createTenantQueryBuilder('contact')
|
|
.andWhere('contact.notification_enabled = true')
|
|
.andWhere('contact.is_verified = true')
|
|
.andWhere(':type = ANY(contact.enabled_notification_types)', { type: notificationType })
|
|
.orderBy('contact.created_at', 'ASC');
|
|
|
|
if (options?.limit) {
|
|
query.take(options.limit);
|
|
}
|
|
if (options?.offset) {
|
|
query.skip(options.offset);
|
|
}
|
|
|
|
const orms = await query.getMany();
|
|
return orms.map(orm => this.toEntity(orm));
|
|
}
|
|
|
|
async countVerifiedByType(): Promise<Record<ContactType, number>> {
|
|
const tenantId = this.getTenantId();
|
|
|
|
const result = await this.repo
|
|
.createQueryBuilder('contact')
|
|
.select('contact.type', 'type')
|
|
.addSelect('COUNT(*)', 'count')
|
|
.where('contact.tenant_id = :tenantId', { tenantId })
|
|
.andWhere('contact.is_verified = true')
|
|
.groupBy('contact.type')
|
|
.getRawMany();
|
|
|
|
const counts: Record<ContactType, number> = {
|
|
[ContactType.EMAIL]: 0,
|
|
[ContactType.WECHAT]: 0,
|
|
[ContactType.WHATSAPP]: 0,
|
|
[ContactType.TELEGRAM]: 0,
|
|
[ContactType.LINE]: 0,
|
|
};
|
|
|
|
for (const row of result) {
|
|
counts[row.type as ContactType] = parseInt(row.count, 10);
|
|
}
|
|
|
|
return counts;
|
|
}
|
|
|
|
private toORM(entity: UserContactEntity): UserContactORM {
|
|
const orm = new UserContactORM();
|
|
orm.id = entity.id;
|
|
orm.tenantId = this.getTenantId();
|
|
orm.userId = entity.userId;
|
|
orm.type = entity.type;
|
|
orm.value = entity.value;
|
|
orm.displayName = entity.displayName;
|
|
orm.isVerified = entity.isVerified;
|
|
orm.verifiedAt = entity.verifiedAt;
|
|
orm.notificationEnabled = entity.notificationEnabled;
|
|
orm.enabledNotificationTypes = entity.enabledNotificationTypes;
|
|
orm.verificationCode = entity.verificationCode;
|
|
orm.verificationExpiresAt = entity.verificationExpiresAt;
|
|
orm.createdAt = entity.createdAt;
|
|
orm.updatedAt = entity.updatedAt;
|
|
return orm;
|
|
}
|
|
|
|
private toEntity(orm: UserContactORM): UserContactEntity {
|
|
return UserContactEntity.fromPersistence({
|
|
id: orm.id,
|
|
userId: orm.userId,
|
|
type: orm.type,
|
|
value: orm.value,
|
|
displayName: orm.displayName,
|
|
isVerified: orm.isVerified,
|
|
verifiedAt: orm.verifiedAt,
|
|
notificationEnabled: orm.notificationEnabled,
|
|
enabledNotificationTypes: orm.enabledNotificationTypes,
|
|
verificationCode: orm.verificationCode,
|
|
verificationExpiresAt: orm.verificationExpiresAt,
|
|
createdAt: orm.createdAt,
|
|
updatedAt: orm.updatedAt,
|
|
});
|
|
}
|
|
}
|