feat: api for booking online

pull/144/head 1.6.1-alpha.1
shancheas 2025-05-28 12:32:11 +07:00
parent 9e361da9cb
commit 7c5b1b3aa8
6 changed files with 218 additions and 13 deletions

View File

@ -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<void> {
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;
}
}

View File

@ -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[];
}

View File

@ -21,15 +21,10 @@ export class ItemController {
async index( async index(
@Query() params: FilterItemDto, @Query() params: FilterItemDto,
): Promise<PaginationResponse<ItemEntity>> { ): Promise<PaginationResponse<ItemEntity>> {
try { params.show_to_booking = true;
params.show_to_booking = true; this.indexManager.setFilterParam(params);
this.indexManager.setFilterParam(params); this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM);
this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM); await this.indexManager.execute();
await this.indexManager.execute(); return this.indexManager.getResult();
return this.indexManager.getResult();
} catch (error) {
console.log(error);
throw error;
}
} }
} }

View File

@ -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<TransactionEntity> {
const payload: Partial<TransactionEntity> = 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();
}
}

View File

@ -6,13 +6,21 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
import { ItemModule } from 'src/modules/item-related/item/item.module'; import { ItemModule } from 'src/modules/item-related/item/item.module';
import { ItemController } from './infrastructure/item.controller'; 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({ @Module({
imports: [ imports: [
ConfigModule.forRoot(), ConfigModule.forRoot(),
TypeOrmModule.forFeature([ItemModel], CONNECTION_NAME.DEFAULT), TypeOrmModule.forFeature([ItemModel], CONNECTION_NAME.DEFAULT),
ItemModule, ItemModule,
TransactionModule,
MidtransModule,
CqrsModule,
], ],
controllers: [ItemController], controllers: [ItemController, BookingOrderController],
providers: [], providers: [CreateBookingManager],
}) })
export class BookingOrderModule {} export class BookingOrderModule {}

View File

@ -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'; import { CouchModule } from 'src/modules/configuration/couch/couch.module';
@Module({ @Module({
exports: [TransactionReadService], exports: [
TransactionReadService,
TransactionDataService,
CreateTransactionManager,
],
imports: [ imports: [
ConfigModule.forRoot(), ConfigModule.forRoot(),
TypeOrmModule.forFeature( TypeOrmModule.forFeature(