diff --git a/src/modules/booking-online/order/domain/usecases/managers/create-booking.manager.ts b/src/modules/booking-online/order/domain/usecases/managers/create-booking.manager.ts new file mode 100644 index 0000000..3febbcb --- /dev/null +++ b/src/modules/booking-online/order/domain/usecases/managers/create-booking.manager.ts @@ -0,0 +1,41 @@ +import { HttpStatus } from '@nestjs/common'; +import { UnprocessableEntityException } from '@nestjs/common'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { CreateTransactionManager } from 'src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager'; +import { generateInvoiceCodeHelper } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/generate-invoice-code.helper'; + +export class CreateBookingManager extends CreateTransactionManager { + async beforeProcess(): Promise { + await super.beforeProcess(); + + const invoiceCode = await generateInvoiceCodeHelper( + this.dataService, + 'BOOK', + ); + + try { + const { token, redirect_url } = await this.dataServiceFirstOpt.create({ + ...this.data, + id: invoiceCode, + }); + Object.assign(this.data, { + payment_midtrans_token: token, + payment_midtrans_url: redirect_url, + }); + } catch (error) { + console.log({ error }); + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Gagal! transaksi telah terbuat, silahkan periksa email untuk melanjutkan pembayaran`, + error: 'Unprocessable Entity', + }); + } + + Object.assign(this.data, { + invoice_code: invoiceCode, + status: STATUS.PENDING, + invoice_date: new Date(), + }); + return; + } +} diff --git a/src/modules/booking-online/order/infrastructure/dto/booking-order.dto.ts b/src/modules/booking-online/order/infrastructure/dto/booking-order.dto.ts new file mode 100644 index 0000000..9c725ab --- /dev/null +++ b/src/modules/booking-online/order/infrastructure/dto/booking-order.dto.ts @@ -0,0 +1,121 @@ +import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.dto'; +import { ApiProperty } from '@nestjs/swagger'; +import { + IsArray, + IsNumber, + IsObject, + IsString, + ValidateIf, +} from 'class-validator'; +import { SeasonPeriodEntity } from 'src/modules/season-related/season-period/domain/entities/season-period.entity'; +import { TransactionItemEntity } from 'src/modules/transaction/transaction/domain/entities/transaction-item.entity'; +import { + TransactionPaymentType, + TransactionUserType, +} from 'src/modules/transaction/transaction/constants'; + +export class TransactionDto extends BaseStatusDto { + @ApiProperty({ + type: Object, + required: false, + example: { + id: 'uuid', + season_type: { + id: 'uuid', + name: 'high season', + }, + }, + }) + @IsObject() + @ValidateIf((body) => body.season_period) + season_period: SeasonPeriodEntity; + + @ApiProperty({ + type: String, + required: true, + example: TransactionUserType.GROUP, + }) + @IsString() + customer_type: TransactionUserType; + + @ApiProperty({ + type: String, + required: true, + example: 'Andika', + }) + @IsString() + customer_name: string; + + @ApiProperty({ + type: String, + required: false, + example: '0823...', + }) + @ValidateIf((body) => body.customer_phone) + customer_phone: string; + + @ApiProperty({ + type: Date, + required: true, + example: '2024-01-01', + }) + booking_date: Date; + + @ApiProperty({ + type: String, + required: false, + example: TransactionPaymentType.MIDTRANS, + }) + payment_type: TransactionPaymentType; + + @ApiProperty({ + type: Number, + required: true, + example: 7000000, + }) + @IsNumber() + payment_sub_total: number; + + @ApiProperty({ + type: Number, + required: true, + example: 3500000, + }) + @IsNumber() + payment_total: number; + + @ApiProperty({ + type: [Object], + required: true, + example: [ + { + item: { + id: '68aa12f7-2cce-422b-9bae-185eb1343b94', + created_at: '1718876384378', + status: 'active', + name: 'tes', + item_type: 'bundling', + hpp: '100000', + base_price: '100000', + limit_type: 'no limit', + limit_value: 0, + item_category: { + id: 'ab15981a-a656-4efc-856c-b2abfbe30979', + name: 'Kategori Bundling 2', + }, + bundling_items: [ + { + id: 'bd5a7a38-df25-4203-a1cd-bf94867946b2', + name: 'Wahana 21 panjangggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg', + }, + ], + tenant: null, + }, + qty: 40, + total_price: 4000000, + }, + ], + }) + @IsArray() + items: TransactionItemEntity[]; +} diff --git a/src/modules/booking-online/order/infrastructure/item.controller.ts b/src/modules/booking-online/order/infrastructure/item.controller.ts index 7a70a07..a3bf89c 100644 --- a/src/modules/booking-online/order/infrastructure/item.controller.ts +++ b/src/modules/booking-online/order/infrastructure/item.controller.ts @@ -21,15 +21,10 @@ export class ItemController { async index( @Query() params: FilterItemDto, ): Promise> { - try { - params.show_to_booking = true; - this.indexManager.setFilterParam(params); - this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM); - await this.indexManager.execute(); - return this.indexManager.getResult(); - } catch (error) { - console.log(error); - throw error; - } + params.show_to_booking = true; + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM); + await this.indexManager.execute(); + return this.indexManager.getResult(); } } diff --git a/src/modules/booking-online/order/infrastructure/order.controller.ts b/src/modules/booking-online/order/infrastructure/order.controller.ts new file mode 100644 index 0000000..d8c1741 --- /dev/null +++ b/src/modules/booking-online/order/infrastructure/order.controller.ts @@ -0,0 +1,36 @@ +import { Body, Controller, Post } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { Public } from 'src/core/guards'; +import { TransactionDto } from './dto/booking-order.dto'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { TransactionType } from 'src/modules/transaction/transaction/constants'; +import { MidtransService } from 'src/modules/configuration/midtrans/data/services/midtrans.service'; +import { CreateBookingManager } from '../domain/usecases/managers/create-booking.manager'; + +@ApiTags('Booking Order') +@Controller('v1/booking') +@Public(true) +export class BookingOrderController { + constructor( + private createBooking: CreateBookingManager, + private serviceData: TransactionDataService, + private midtransService: MidtransService, + ) {} + + @Post() + async create(@Body() data: TransactionDto): Promise { + const payload: Partial = data; + payload.type = TransactionType.ONLINE; + + this.createBooking.setData(payload as any); + this.createBooking.setService( + this.serviceData, + TABLE_NAME.TRANSACTION, + this.midtransService, + ); + await this.createBooking.execute(); + return this.createBooking.getResult(); + } +} diff --git a/src/modules/booking-online/order/order.module.ts b/src/modules/booking-online/order/order.module.ts index 7a2203b..6a5c4b4 100644 --- a/src/modules/booking-online/order/order.module.ts +++ b/src/modules/booking-online/order/order.module.ts @@ -6,13 +6,21 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; import { ItemModule } from 'src/modules/item-related/item/item.module'; import { ItemController } from './infrastructure/item.controller'; +import { TransactionModule } from 'src/modules/transaction/transaction/transaction.module'; +import { BookingOrderController } from './infrastructure/order.controller'; +import { CreateBookingManager } from './domain/usecases/managers/create-booking.manager'; +import { MidtransModule } from 'src/modules/configuration/midtrans/midtrans.module'; +import { CqrsModule } from '@nestjs/cqrs'; @Module({ imports: [ ConfigModule.forRoot(), TypeOrmModule.forFeature([ItemModel], CONNECTION_NAME.DEFAULT), ItemModule, + TransactionModule, + MidtransModule, + CqrsModule, ], - controllers: [ItemController], - providers: [], + controllers: [ItemController, BookingOrderController], + providers: [CreateBookingManager], }) export class BookingOrderModule {} diff --git a/src/modules/transaction/transaction/transaction.module.ts b/src/modules/transaction/transaction/transaction.module.ts index 7803e20..af14bef 100644 --- a/src/modules/transaction/transaction/transaction.module.ts +++ b/src/modules/transaction/transaction/transaction.module.ts @@ -49,7 +49,11 @@ import { ItemModel } from 'src/modules/item-related/item/data/models/item.model' import { CouchModule } from 'src/modules/configuration/couch/couch.module'; @Module({ - exports: [TransactionReadService], + exports: [ + TransactionReadService, + TransactionDataService, + CreateTransactionManager, + ], imports: [ ConfigModule.forRoot(), TypeOrmModule.forFeature(