From dc926d84e4bcff76ed58dbb6fe420b5ec327d590 Mon Sep 17 00:00:00 2001 From: shancheas Date: Wed, 11 Jun 2025 10:35:06 +0700 Subject: [PATCH] refactor: streamline rescheduling logic and enhance transaction retrieval - Replaced direct transaction retrieval with a dedicated method for better clarity. - Consolidated validation checks for rescheduling into the controller. - Added booking date to the transaction data being created. - Improved error handling for various transaction states during rescheduling. --- .../usecases/managers/reschedule.manager.ts | 36 +++------------ .../order/infrastructure/order.controller.ts | 44 ++++++++++++++++++- .../data/services/transaction-data.service.ts | 7 +++ 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/modules/booking-online/order/domain/usecases/managers/reschedule.manager.ts b/src/modules/booking-online/order/domain/usecases/managers/reschedule.manager.ts index 6d526bb..cb67563 100644 --- a/src/modules/booking-online/order/domain/usecases/managers/reschedule.manager.ts +++ b/src/modules/booking-online/order/domain/usecases/managers/reschedule.manager.ts @@ -14,38 +14,11 @@ export class RescheduleManager { constructor(private serviceData: TransactionDataService) {} async reschedule(data: RescheduleVerificationModel) { - const transaction = await this.serviceData.getRepository().findOne({ - relations: ['children_transactions', 'items'], - where: { id: data.booking_id }, - }); + const transaction = await this.serviceData.getTransactionWithReschedule( + data.booking_id, + ); - const today = moment().startOf('day'); const rescheduleDate = moment(data.reschedule_date, 'DD-MM-YYYY'); - const rescheduleDateStartOfDay = rescheduleDate.startOf('day'); - - //TODO: validate session period priority - - if (rescheduleDateStartOfDay.isSameOrBefore(today)) { - throw new UnprocessableEntityException( - 'Reschedule date must be in the future', - ); - } - - if (!transaction) { - throw new UnprocessableEntityException('Transaction not found'); - } - - if (transaction.status !== STATUS.SETTLED) { - throw new UnprocessableEntityException('Transaction is not settled'); - } - - if (transaction.children_transactions.length > 0) { - throw new UnprocessableEntityException('Transaction already rescheduled'); - } - - if (transaction.parent_id) { - throw new UnprocessableEntityException('Transaction is a reschedule'); - } const id = uuidv4(); const invoiceCode = await generateInvoiceCodeHelper( @@ -62,6 +35,7 @@ export class RescheduleManager { invoice_code: invoiceCode, status: STATUS.SETTLED, invoice_date: rescheduleDate.format('YYYY-MM-DD'), + booking_date: rescheduleDate.format('YYYY-MM-DD'), created_at: moment().unix() * 1000, updated_at: moment().unix() * 1000, items, @@ -75,7 +49,7 @@ export class RescheduleManager { name: transactionData.customer_name, phone: transactionData.customer_phone, time: moment(transactionData.invoice_date).unix() * 1000, - code: data.code.toString(), + code: transactionData.invoice_code, }); return transactionData; diff --git a/src/modules/booking-online/order/infrastructure/order.controller.ts b/src/modules/booking-online/order/infrastructure/order.controller.ts index db38439..fcaebc9 100644 --- a/src/modules/booking-online/order/infrastructure/order.controller.ts +++ b/src/modules/booking-online/order/infrastructure/order.controller.ts @@ -1,4 +1,12 @@ -import { Body, Controller, Get, Param, Post, Res } from '@nestjs/common'; +import { + Body, + Controller, + Get, + Param, + Post, + Res, + UnprocessableEntityException, +} from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Public } from 'src/core/guards'; import { TransactionDto } from './dto/booking-order.dto'; @@ -16,6 +24,8 @@ import { } from './dto/reschedule.dto'; import { RescheduleVerificationManager } from '../domain/usecases/managers/reschedule-verification.manager'; import { RescheduleManager } from '../domain/usecases/managers/reschedule.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import * as moment from 'moment'; @ApiTags('Booking Order') @Controller('v1/booking') @@ -60,6 +70,38 @@ export class BookingOrderController { @Post('reschedule') async reschedule(@Body() data: RescheduleRequestDTO) { + const transaction = await this.serviceData.getTransactionWithReschedule( + data.booking_id, + ); + + const today = moment().startOf('day'); + const rescheduleDate = moment(data.reschedule_date, 'DD-MM-YYYY'); + const rescheduleDateStartOfDay = rescheduleDate.startOf('day'); + + //TODO: validate session period priority + + if (rescheduleDateStartOfDay.isSameOrBefore(today)) { + throw new UnprocessableEntityException( + 'Reschedule date must be in the future', + ); + } + + if (!transaction) { + throw new UnprocessableEntityException('Transaction not found'); + } + + if (transaction.status !== STATUS.SETTLED) { + throw new UnprocessableEntityException('Transaction is not settled'); + } + + if (transaction.children_transactions.length > 0) { + throw new UnprocessableEntityException('Transaction already rescheduled'); + } + + if (transaction.parent_id) { + throw new UnprocessableEntityException('Transaction is a reschedule'); + } + const result = await this.rescheduleVerification.saveVerification(data); const maskedPhoneNumber = result.phone_number.replace(/.(?=.{4})/g, '*'); result.phone_number = maskedPhoneNumber; diff --git a/src/modules/transaction/transaction/data/services/transaction-data.service.ts b/src/modules/transaction/transaction/data/services/transaction-data.service.ts index 40b8f6a..827be1c 100644 --- a/src/modules/transaction/transaction/data/services/transaction-data.service.ts +++ b/src/modules/transaction/transaction/data/services/transaction-data.service.ts @@ -13,4 +13,11 @@ export class TransactionDataService extends BaseDataService { ) { super(repo); } + + async getTransactionWithReschedule(booking_id: string) { + return this.repo.findOne({ + relations: ['children_transactions', 'items'], + where: { id: booking_id }, + }); + } }