Compare commits
4 Commits
18afc47030
...
399ca0bdda
Author | SHA1 | Date |
---|---|---|
|
399ca0bdda | |
|
b8dd2a4e01 | |
|
6a7ab72e12 | |
|
ffc75ba174 |
|
@ -0,0 +1,19 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddBookingDescriptionToItem1749537252986
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'AddBookingDescriptionToItem1749537252986';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" ADD "booking_description" text`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "items" DROP COLUMN "booking_description"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { TransactionType } from 'src/modules/transaction/transaction/constants';
|
||||||
import { CreateTransactionManager } from 'src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager';
|
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';
|
import { generateInvoiceCodeHelper } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/generate-invoice-code.helper';
|
||||||
import { mappingRevertTransaction } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper';
|
import { mappingRevertTransaction } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper';
|
||||||
|
import { WhatsappService } from 'src/services/whatsapp/whatsapp.service';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export class CreateBookingManager extends CreateTransactionManager {
|
export class CreateBookingManager extends CreateTransactionManager {
|
||||||
|
@ -43,4 +44,20 @@ export class CreateBookingManager extends CreateTransactionManager {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async afterProcess(): Promise<void> {
|
||||||
|
const whatsapp = new WhatsappService();
|
||||||
|
console.log(`/snap/v4/redirection/${this.data.payment_midtrans_token}`);
|
||||||
|
console.log(this.data.payment_midtrans_url);
|
||||||
|
await whatsapp.bookingRegister(
|
||||||
|
{
|
||||||
|
phone: this.data.customer_phone,
|
||||||
|
code: this.data.invoice_code,
|
||||||
|
name: this.data.customer_name,
|
||||||
|
time: this.data.booking_date,
|
||||||
|
id: this.data.id,
|
||||||
|
},
|
||||||
|
`snap/v4/redirection/${this.data.payment_midtrans_token}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,13 @@ export class RescheduleVerificationManager {
|
||||||
phone: transaction.customer_phone,
|
phone: transaction.customer_phone,
|
||||||
code: otp.toString(),
|
code: otp.toString(),
|
||||||
});
|
});
|
||||||
|
// whatsapp.bookingReschedule({
|
||||||
|
// phone: transaction.customer_phone,
|
||||||
|
// code: otp.toString(),
|
||||||
|
// name: transaction.customer_name,
|
||||||
|
// time: new Date(request.reschedule_date).getTime(),
|
||||||
|
// id: transaction.id,
|
||||||
|
// });
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// You can customize the error handling as needed, e.g., throw HttpException for NestJS
|
// You can customize the error handling as needed, e.g., throw HttpException for NestJS
|
||||||
|
|
|
@ -27,6 +27,9 @@ export class ItemModel
|
||||||
@Column('varchar', { name: 'name', unique: true })
|
@Column('varchar', { name: 'name', unique: true })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
@Column('text', { name: 'booking_description', nullable: true })
|
||||||
|
booking_description: string;
|
||||||
|
|
||||||
@Column('varchar', { name: 'image_url', nullable: true })
|
@Column('varchar', { name: 'image_url', nullable: true })
|
||||||
image_url: string;
|
image_url: string;
|
||||||
|
|
||||||
|
|
|
@ -18,4 +18,5 @@ export interface ItemEntity extends BaseStatusEntity {
|
||||||
use_queue: boolean;
|
use_queue: boolean;
|
||||||
show_to_booking: boolean;
|
show_to_booking: boolean;
|
||||||
breakdown_bundling?: boolean;
|
breakdown_bundling?: boolean;
|
||||||
|
booking_description?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ export class DetailItemManager extends BaseDetailManager<ItemEntity> {
|
||||||
`${this.tableName}.show_to_booking`,
|
`${this.tableName}.show_to_booking`,
|
||||||
`${this.tableName}.breakdown_bundling`,
|
`${this.tableName}.breakdown_bundling`,
|
||||||
`${this.tableName}.play_estimation`,
|
`${this.tableName}.play_estimation`,
|
||||||
|
`${this.tableName}.booking_description`,
|
||||||
|
|
||||||
`item_category.id`,
|
`item_category.id`,
|
||||||
`item_category.name`,
|
`item_category.name`,
|
||||||
|
|
|
@ -54,6 +54,7 @@ export class IndexItemManager extends BaseIndexManager<ItemEntity> {
|
||||||
`${this.tableName}.breakdown_bundling`,
|
`${this.tableName}.breakdown_bundling`,
|
||||||
`${this.tableName}.play_estimation`,
|
`${this.tableName}.play_estimation`,
|
||||||
`${this.tableName}.show_to_booking`,
|
`${this.tableName}.show_to_booking`,
|
||||||
|
`${this.tableName}.booking_description`,
|
||||||
|
|
||||||
`item_category.id`,
|
`item_category.id`,
|
||||||
`item_category.name`,
|
`item_category.name`,
|
||||||
|
|
|
@ -138,6 +138,17 @@ export class ItemDto extends BaseStatusDto implements ItemEntity {
|
||||||
@ValidateIf((body) => body.show_to_booking)
|
@ValidateIf((body) => body.show_to_booking)
|
||||||
show_to_booking: boolean;
|
show_to_booking: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
example: '...',
|
||||||
|
})
|
||||||
|
@ValidateIf((body) => body.show_to_booking)
|
||||||
|
@IsString({
|
||||||
|
message: 'Booking description is required when show to booking is enabled.',
|
||||||
|
})
|
||||||
|
booking_description: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
name: 'bundling_items',
|
name: 'bundling_items',
|
||||||
type: [Object],
|
type: [Object],
|
||||||
|
|
|
@ -199,6 +199,118 @@ export class WhatsappService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async bookingRegister(data: WhatsappBookingCreate, paymentUrl: string) {
|
||||||
|
const momentDate = moment(data.time);
|
||||||
|
const fallbackValue = momentDate.locale('id').format('dddd, DD MMMM YYYY');
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
messaging_product: 'whatsapp',
|
||||||
|
to: phoneNumberOnly(data.phone), // recipient's phone number
|
||||||
|
type: 'template',
|
||||||
|
template: {
|
||||||
|
name: 'booking_register',
|
||||||
|
language: {
|
||||||
|
code: 'id', // language code
|
||||||
|
},
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
type: 'body',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'customer',
|
||||||
|
text: data.name, // replace with name variable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'booking_date',
|
||||||
|
text: fallbackValue,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
sub_type: 'url',
|
||||||
|
index: '0',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: paymentUrl, // replace with dynamic URL
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await this.sendMessage(payload);
|
||||||
|
if (response)
|
||||||
|
Logger.log(
|
||||||
|
`Notification register Booking for ${data.code} send to ${data.phone}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async bookingReschedule(data: WhatsappBookingCreate) {
|
||||||
|
const momentDate = moment(data.time);
|
||||||
|
const fallbackValue = momentDate.locale('id').format('dddd, DD MMMM YYYY');
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
messaging_product: 'whatsapp',
|
||||||
|
to: phoneNumberOnly(data.phone), // recipient's phone number
|
||||||
|
type: 'template',
|
||||||
|
template: {
|
||||||
|
name: 'booking_reschedule',
|
||||||
|
language: {
|
||||||
|
code: 'id', // language code
|
||||||
|
},
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
type: 'body',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'customer',
|
||||||
|
text: data.name, // replace with name variable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'booking_code',
|
||||||
|
text: data.code, // replace with queue_code variable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'booking_date',
|
||||||
|
text: fallbackValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
parameter_name: 'otp',
|
||||||
|
text: data.code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
sub_type: 'copy_code',
|
||||||
|
index: '0',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
type: 'coupon_code',
|
||||||
|
coupon_code: data.code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await this.sendMessage(payload);
|
||||||
|
if (response)
|
||||||
|
Logger.log(
|
||||||
|
`Notification reschedule Booking for ${data.code} send to ${data.phone}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async sendOtpNotification(data: { phone: string; code: string }) {
|
async sendOtpNotification(data: { phone: string; code: string }) {
|
||||||
// Compose the WhatsApp message payload for OTP using Facebook WhatsApp API
|
// Compose the WhatsApp message payload for OTP using Facebook WhatsApp API
|
||||||
const payload = {
|
const payload = {
|
||||||
|
|
Loading…
Reference in New Issue