pos-be/src/modules/booking-online/order/domain/usecases/managers/reschedule-verification.man...

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;
}
}