106 lines
3.5 KiB
TypeScript
106 lines
3.5 KiB
TypeScript
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { RescheduleVerificationModel } from '../../../data/models/reschedule-verification.model';
|
|
import {
|
|
RescheduleRequest,
|
|
RescheduleVerification,
|
|
} from '../../entities/reschedule-verification.entity';
|
|
import { generateOtp } from 'src/modules/booking-online/helpers/generate-otp';
|
|
import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service';
|
|
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
|
|
import { WhatsappService } from 'src/services/whatsapp/whatsapp.service';
|
|
|
|
@Injectable()
|
|
export class RescheduleVerificationManager {
|
|
constructor(
|
|
@InjectRepository(RescheduleVerificationModel)
|
|
private readonly rescheduleVerificationRepository: Repository<RescheduleVerificationModel>,
|
|
private readonly transactionService: TransactionReadService,
|
|
) {}
|
|
|
|
async saveVerification(
|
|
request: RescheduleRequest,
|
|
): Promise<RescheduleVerificationModel> {
|
|
try {
|
|
const otp = generateOtp();
|
|
const transaction = await this.findDetailByBookingId(request.booking_id);
|
|
|
|
if (!transaction) {
|
|
throw new Error('Transaction not found for the provided booking id');
|
|
}
|
|
|
|
const data: Partial<RescheduleVerification> = {
|
|
code: otp,
|
|
booking_id: transaction.id,
|
|
name: transaction.customer_name,
|
|
phone_number: transaction.customer_phone,
|
|
reschedule_date: request.reschedule_date,
|
|
};
|
|
|
|
const existTransaction =
|
|
await this.rescheduleVerificationRepository.findOne({
|
|
where: {
|
|
booking_id: transaction.id,
|
|
},
|
|
});
|
|
|
|
const verification =
|
|
existTransaction ?? this.rescheduleVerificationRepository.create(data);
|
|
const result = await this.rescheduleVerificationRepository.save({
|
|
...verification,
|
|
code: otp,
|
|
});
|
|
|
|
const whatsapp = new WhatsappService();
|
|
whatsapp.sendOtpNotification({
|
|
phone: transaction.customer_phone,
|
|
code: otp.toString(),
|
|
});
|
|
return result;
|
|
} catch (error) {
|
|
// You can customize the error handling as needed, e.g., throw HttpException for NestJS
|
|
throw new UnprocessableEntityException(
|
|
`Failed to save reschedule verification: ${error.message}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async verifyOtp(
|
|
booking_id: string,
|
|
code: number,
|
|
): Promise<{ success: boolean; message: string }> {
|
|
const verification = await this.rescheduleVerificationRepository.findOne({
|
|
where: { booking_id, code },
|
|
order: { created_at: 'DESC' },
|
|
});
|
|
|
|
if (!verification) {
|
|
return {
|
|
success: false,
|
|
message: 'No verification code found for this booking.',
|
|
};
|
|
}
|
|
|
|
// Optionally, you can implement OTP expiration logic here
|
|
|
|
if (verification.code !== code) {
|
|
// Increment tried count
|
|
verification.tried = (verification.tried || 0) + 1;
|
|
await this.rescheduleVerificationRepository.save(verification);
|
|
return { success: false, message: 'Invalid verification code.' };
|
|
}
|
|
|
|
// Optionally, you can mark the verification as used or verified here
|
|
|
|
return { success: true, message: 'Verification successful.' };
|
|
}
|
|
|
|
async findDetailByBookingId(bookingId: string): Promise<TransactionEntity> {
|
|
const transaction = await this.transactionService.getOneByOptions({
|
|
where: { id: bookingId },
|
|
});
|
|
return transaction;
|
|
}
|
|
}
|