From 82e78799694bb6da76edf0106eef5f89db67d978 Mon Sep 17 00:00:00 2001 From: shancheas Date: Sat, 21 Dec 2024 03:56:13 +0700 Subject: [PATCH 1/4] feat: add configuration for whatsapp service --- ...8-add-notification-config-to-item-queue.ts | 25 +++++++++++++++++++ ...18462106-add-last-notification-to-queue.ts | 19 ++++++++++++++ .../data/models/item-queue.model.ts | 6 +++++ .../domain/entities/item-queue.entity.ts | 2 ++ .../managers/detail-item-queue.manager.ts | 2 ++ .../managers/index-item-queue.manager.ts | 2 ++ src/modules/queue/data/models/queue.model.ts | 3 +++ .../queue/domain/helpers/time.helper.ts | 13 ++++++++++ 8 files changed, 72 insertions(+) create mode 100644 src/database/migrations/1734717058658-add-notification-config-to-item-queue.ts create mode 100644 src/database/migrations/1734718462106-add-last-notification-to-queue.ts diff --git a/src/database/migrations/1734717058658-add-notification-config-to-item-queue.ts b/src/database/migrations/1734717058658-add-notification-config-to-item-queue.ts new file mode 100644 index 0000000..98f329d --- /dev/null +++ b/src/database/migrations/1734717058658-add-notification-config-to-item-queue.ts @@ -0,0 +1,25 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddNotificationConfigToItemQueue1734717058658 + implements MigrationInterface +{ + name = 'AddNotificationConfigToItemQueue1734717058658'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "item_queues" ADD "use_notification" boolean NOT NULL DEFAULT true`, + ); + await queryRunner.query( + `ALTER TABLE "item_queues" ADD "requiring_notification" boolean NOT NULL DEFAULT false`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "item_queues" DROP COLUMN "requiring_notification"`, + ); + await queryRunner.query( + `ALTER TABLE "item_queues" DROP COLUMN "use_notification"`, + ); + } +} diff --git a/src/database/migrations/1734718462106-add-last-notification-to-queue.ts b/src/database/migrations/1734718462106-add-last-notification-to-queue.ts new file mode 100644 index 0000000..1334c16 --- /dev/null +++ b/src/database/migrations/1734718462106-add-last-notification-to-queue.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddLastNotificationToQueue1734718462106 + implements MigrationInterface +{ + name = 'AddLastNotificationToQueue1734718462106'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "queues" ADD "last_notification" bigint NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "queues" DROP COLUMN "last_notification"`, + ); + } +} diff --git a/src/modules/item-related/item-queue/data/models/item-queue.model.ts b/src/modules/item-related/item-queue/data/models/item-queue.model.ts index 7f0be80..c298f6d 100644 --- a/src/modules/item-related/item-queue/data/models/item-queue.model.ts +++ b/src/modules/item-related/item-queue/data/models/item-queue.model.ts @@ -33,4 +33,10 @@ export class ItemQueueModel onUpdate: 'CASCADE', }) items: ItemModel[]; + + @Column('boolean', { default: true }) + use_notification: boolean; + + @Column('boolean', { default: false }) + requiring_notification: boolean; } diff --git a/src/modules/item-related/item-queue/domain/entities/item-queue.entity.ts b/src/modules/item-related/item-queue/domain/entities/item-queue.entity.ts index 5b89cfe..1d7c765 100644 --- a/src/modules/item-related/item-queue/domain/entities/item-queue.entity.ts +++ b/src/modules/item-related/item-queue/domain/entities/item-queue.entity.ts @@ -9,4 +9,6 @@ export interface ItemQueueEntity extends BaseStatusEntity { max_peak_level: number; call_preparation: number; items: ItemEntity[]; + use_notification?: boolean; + requiring_notification?: boolean; } diff --git a/src/modules/item-related/item-queue/domain/usecases/managers/detail-item-queue.manager.ts b/src/modules/item-related/item-queue/domain/usecases/managers/detail-item-queue.manager.ts index 67d7861..2686425 100644 --- a/src/modules/item-related/item-queue/domain/usecases/managers/detail-item-queue.manager.ts +++ b/src/modules/item-related/item-queue/domain/usecases/managers/detail-item-queue.manager.ts @@ -38,6 +38,8 @@ export class DetailItemQueueManager extends BaseDetailManager { `${this.tableName}.editor_name`, `${this.tableName}.max_peak_level`, `${this.tableName}.call_preparation`, + `${this.tableName}.use_notification`, + `${this.tableName}.requiring_notification`, `items.id`, `items.created_at`, diff --git a/src/modules/item-related/item-queue/domain/usecases/managers/index-item-queue.manager.ts b/src/modules/item-related/item-queue/domain/usecases/managers/index-item-queue.manager.ts index 93c6eb8..a0c94b5 100644 --- a/src/modules/item-related/item-queue/domain/usecases/managers/index-item-queue.manager.ts +++ b/src/modules/item-related/item-queue/domain/usecases/managers/index-item-queue.manager.ts @@ -41,6 +41,8 @@ export class IndexItemQueueManager extends BaseIndexManager { `${this.tableName}.editor_name`, `${this.tableName}.max_peak_level`, `${this.tableName}.call_preparation`, + `${this.tableName}.use_notification`, + `${this.tableName}.requiring_notification`, `items.id`, `items.created_at`, diff --git a/src/modules/queue/data/models/queue.model.ts b/src/modules/queue/data/models/queue.model.ts index eff707f..dd3ec16 100644 --- a/src/modules/queue/data/models/queue.model.ts +++ b/src/modules/queue/data/models/queue.model.ts @@ -115,6 +115,9 @@ export class QueueModel extends BaseModel implements Queue { @Column({ type: 'bigint' }) time: number; + @Column({ type: 'bigint', nullable: true }) + last_notification: number; + @Column({ type: 'bigint' }) call_time: number; diff --git a/src/modules/queue/domain/helpers/time.helper.ts b/src/modules/queue/domain/helpers/time.helper.ts index 88f094e..8a5e05f 100644 --- a/src/modules/queue/domain/helpers/time.helper.ts +++ b/src/modules/queue/domain/helpers/time.helper.ts @@ -9,3 +9,16 @@ export function toTime(timestamp: number): string { minutes < 10 ? '0' : '' }${minutes}`; } + +export function phoneNumberOnly(phone: string): string { + return phone.replace(/[^0-9]/g, ''); +} + +export function timeIsBefore( + currentTime: number, + time: number, + diff = 15, +): boolean { + const diffInMilliseconds = diff * 60 * 1000; + return time < currentTime + diffInMilliseconds; +} -- 2.40.1 From 44e74de315801786abc9f03ff6a2f748a391a60f Mon Sep 17 00:00:00 2001 From: shancheas Date: Sat, 21 Dec 2024 04:01:54 +0700 Subject: [PATCH 2/4] feat: whatsapp notification --- env/env.development | 5 +- env/env.production | 5 +- .../queue/data/services/queue.service.ts | 14 ++ .../queue/domain/queue-admin.orchestrator.ts | 46 +++++ .../domain/usecases/register-queue.manager.ts | 20 +++ .../controllers/queue-job.controller.ts | 23 +++ src/modules/queue/queue.module.ts | 3 +- .../whatsapp/entity/whatsapp-queue.entity.ts | 8 + src/services/whatsapp/whatsapp.constant.ts | 14 ++ src/services/whatsapp/whatsapp.helper.ts | 62 +++++++ src/services/whatsapp/whatsapp.service.ts | 158 ++++++++++++++++++ 11 files changed, 355 insertions(+), 3 deletions(-) create mode 100644 src/modules/queue/infrastructure/controllers/queue-job.controller.ts create mode 100644 src/services/whatsapp/entity/whatsapp-queue.entity.ts create mode 100644 src/services/whatsapp/whatsapp.constant.ts create mode 100644 src/services/whatsapp/whatsapp.helper.ts create mode 100644 src/services/whatsapp/whatsapp.service.ts diff --git a/env/env.development b/env/env.development index 4fb5ad3..1e241d4 100644 --- a/env/env.development +++ b/env/env.development @@ -43,4 +43,7 @@ GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec1 SUPERSET_URL=https://dashboard.weplayground.eigen.co.id SUPERSET_ADMIN_USERNAME=admin -SUPERSET_ADMIN_PASSWORD=admin \ No newline at end of file +SUPERSET_ADMIN_PASSWORD=admin + +WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID=604883366037548 +WHATSAPP_BUSINESS_ACCESS_TOKEN=EAAINOvRRiEEBO9yQsYDnYtjHZB7q1nZCwbBpRcxIGMDWajKZBtmWxNRKvPYkS95KQZBsZBOvSFyjiEg5CcCZBZBtaSZApxyV8fiA3cEyVwf7iVZBQP2YCTPRQZArMFeeXbO0uq5TGygmjsIz3M4YxcUHxPzKO4pKxIyxnzcoUZCqCSo1NqQSLVf3a0JyZAwgDXGL55dV \ No newline at end of file diff --git a/env/env.production b/env/env.production index 5557402..fce7b16 100644 --- a/env/env.production +++ b/env/env.production @@ -40,4 +40,7 @@ GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec1 SUPERSET_URL=https://dashboard.weplayground.eigen.co.id SUPERSET_ADMIN_USERNAME=admin -SUPERSET_ADMIN_PASSWORD=admin \ No newline at end of file +SUPERSET_ADMIN_PASSWORD=admin + +WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID=604883366037548 +WHATSAPP_BUSINESS_ACCESS_TOKEN=EAAINOvRRiEEBO9yQsYDnYtjHZB7q1nZCwbBpRcxIGMDWajKZBtmWxNRKvPYkS95KQZBsZBOvSFyjiEg5CcCZBZBtaSZApxyV8fiA3cEyVwf7iVZBQP2YCTPRQZArMFeeXbO0uq5TGygmjsIz3M4YxcUHxPzKO4pKxIyxnzcoUZCqCSo1NqQSLVf3a0JyZAwgDXGL55dV \ No newline at end of file diff --git a/src/modules/queue/data/services/queue.service.ts b/src/modules/queue/data/services/queue.service.ts index bb03a82..dbdd946 100644 --- a/src/modules/queue/data/services/queue.service.ts +++ b/src/modules/queue/data/services/queue.service.ts @@ -165,6 +165,15 @@ export class QueueService extends BaseDataService { super(repo); } + async queueTicket(queueId: string) { + return this.repo.findOne({ + relations: ['item', 'item.ticket'], + where: { + id: queueId, + }, + }); + } + async queues(ids: string[]) { const start = moment().startOf('day').valueOf(); const end = moment().endOf('day').valueOf(); @@ -225,6 +234,11 @@ export class QueueService extends BaseDataService { }); } + async updateLastNotification(queue_id: string, time: number) { + const query = `UPDATE queues SET last_notification = ${time} WHERE id = '${queue_id}'`; + this.dataSource.query(query); + } + async updateItemQty(item_id: string, qty: number): Promise { const query = `UPDATE queue_items SET qty = qty - ${qty} WHERE id = '${item_id}'`; this.dataSource.query(query); diff --git a/src/modules/queue/domain/queue-admin.orchestrator.ts b/src/modules/queue/domain/queue-admin.orchestrator.ts index 30d6b4d..96d6214 100644 --- a/src/modules/queue/domain/queue-admin.orchestrator.ts +++ b/src/modules/queue/domain/queue-admin.orchestrator.ts @@ -12,6 +12,11 @@ import { ORDER_TYPE, QUEUE_STATUS, } from 'src/core/strings/constants/base.constants'; +import { QueueTimeFormula } from './usecases/formula/queue-time.formula'; +import * as moment from 'moment'; +import { timeIsBefore, toTime } from './helpers/time.helper'; +import { WhatsappService } from 'src/services/whatsapp/whatsapp.service'; +import { WhatsappQueue } from 'src/services/whatsapp/entity/whatsapp-queue.entity'; @Injectable() export class QueueAdminOrchestrator { @@ -21,6 +26,7 @@ export class QueueAdminOrchestrator { private indexManager: IndexQueueManager, private callManager: CallQueueManager, private doneManager: DoneQueueManager, + private readonly queueTimeFormula: QueueTimeFormula, ) {} async index(params): Promise> { @@ -43,4 +49,44 @@ export class QueueAdminOrchestrator { await this.doneManager.execute(); return this.doneManager.getResult(); } + + async job(): Promise { + const notification = new WhatsappService(); + const itemMasters = await this.dataService.allQueue(); + const currentTime = moment().valueOf(); + + for (const queueItem of itemMasters) { + const queueTimes = await this.queueTimeFormula.items(queueItem.id); + if (!queueItem.use_notification) continue; + + for (const queueId in queueTimes) { + const callTime = queueTimes[queueId]; + + if (timeIsBefore(currentTime, callTime, queueItem.call_preparation)) { + const queueTicket = await this.service.queueTicket(queueId); + const payload: WhatsappQueue = { + id: queueId, + phone: queueTicket.item.ticket.phone, + code: queueTicket.code, + name: queueTicket.item.ticket.customer, + item_name: queueItem.name, + time: callTime, + }; + + console.log({ + currentTime: toTime(currentTime), + callTime: toTime(callTime), + last_notification: toTime(queueTicket.last_notification), + queueId, + }); + + const call_preparation = queueItem.call_preparation * 60 * 1000; + if (queueTicket.last_notification < currentTime - call_preparation) { + await notification.queueProcess(payload); + this.service.updateLastNotification(queueId, currentTime); + } + } + } + } + } } diff --git a/src/modules/queue/domain/usecases/register-queue.manager.ts b/src/modules/queue/domain/usecases/register-queue.manager.ts index 90ec7d6..f942322 100644 --- a/src/modules/queue/domain/usecases/register-queue.manager.ts +++ b/src/modules/queue/domain/usecases/register-queue.manager.ts @@ -11,6 +11,8 @@ import { padCode } from 'src/modules/transaction/vip-code/domain/usecases/manage import { QueueBucketReadService } from '../../data/services/queue-bucket'; import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; import { QueueTimeFormula } from './formula/queue-time.formula'; +import { WhatsappService } from 'src/services/whatsapp/whatsapp.service'; +import { WhatsappQueue } from 'src/services/whatsapp/entity/whatsapp-queue.entity'; import * as moment from 'moment'; @Injectable() @@ -22,6 +24,8 @@ export class RegisterQueueManager extends BaseCreateManager { super(); } + private currentItemMaster; + async averageTime(): Promise { const item = await this.getItemMaster(); return item.play_estimation; @@ -40,6 +44,7 @@ export class RegisterQueueManager extends BaseCreateManager { async beforeProcess(): Promise { const vip = this.data.vip ?? false; const item = await this.getItemMaster(); + this.currentItemMaster = item; const [, end] = await this.queueTime(item.item_queue_id); const queueNumber = await this.bucketService.getQueue( @@ -71,6 +76,21 @@ export class RegisterQueueManager extends BaseCreateManager { } async afterProcess(): Promise { + const notificationService = new WhatsappService(); + const item = this.currentItemMaster ?? (await this.getItemMaster()); + const queueTicket = await this.dataService.queueTicket(this.result.id); + + const payload: WhatsappQueue = { + id: this.result.id, + phone: queueTicket.item.ticket.phone, + code: this.result.code, + name: queueTicket.item.ticket.customer, + item_name: item.name, + time: this.result.time, + }; + notificationService.queueRegister(payload); + const currentTime = moment().valueOf(); + this.dataService.updateLastNotification(this.result.id, currentTime); return; } diff --git a/src/modules/queue/infrastructure/controllers/queue-job.controller.ts b/src/modules/queue/infrastructure/controllers/queue-job.controller.ts new file mode 100644 index 0000000..006b834 --- /dev/null +++ b/src/modules/queue/infrastructure/controllers/queue-job.controller.ts @@ -0,0 +1,23 @@ +import { Controller, Logger, Post } from '@nestjs/common'; + +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; + +import { QueueAdminOrchestrator } from '../../domain/queue-admin.orchestrator'; +import { Public } from 'src/core/guards'; +// import { Cron } from '@nestjs/schedule'; + +@ApiTags(`Queue Admin`) +@Controller(`v1/${MODULE_NAME.QUEUE}-job`) +@ApiBearerAuth('JWT') +@Public(true) +export class QueueJobController { + constructor(private orchestrator: QueueAdminOrchestrator) {} + + // @Cron('*/1 * * * *') + @Post('queues/notification') + async call() { + Logger.log('call preparation'); + return this.orchestrator.job(); + } +} diff --git a/src/modules/queue/queue.module.ts b/src/modules/queue/queue.module.ts index a117956..e0c96d3 100644 --- a/src/modules/queue/queue.module.ts +++ b/src/modules/queue/queue.module.ts @@ -37,6 +37,7 @@ import { SplitQueueManager } from './domain/usecases/split-queue.manager'; import { QueueTransactionCancelHandler } from './infrastructure/handlers/cancel-transaction.handler'; import { ItemQueueModel } from '../item-related/item-queue/data/models/item-queue.model'; import { QueueTimeFormula } from './domain/usecases/formula/queue-time.formula'; +import { QueueJobController } from './infrastructure/controllers/queue-job.controller'; @Module({ imports: [ @@ -56,7 +57,7 @@ import { QueueTimeFormula } from './domain/usecases/formula/queue-time.formula'; ), CqrsModule, ], - controllers: [QueueController, QueueAdminController], + controllers: [QueueController, QueueAdminController, QueueJobController], providers: [ QueueOrchestrator, QueueAdminOrchestrator, diff --git a/src/services/whatsapp/entity/whatsapp-queue.entity.ts b/src/services/whatsapp/entity/whatsapp-queue.entity.ts new file mode 100644 index 0000000..0b169e7 --- /dev/null +++ b/src/services/whatsapp/entity/whatsapp-queue.entity.ts @@ -0,0 +1,8 @@ +export interface WhatsappQueue { + id: string; + phone: string; + code: string; + name: string; + item_name: string; + time: number; +} diff --git a/src/services/whatsapp/whatsapp.constant.ts b/src/services/whatsapp/whatsapp.constant.ts new file mode 100644 index 0000000..0f568ca --- /dev/null +++ b/src/services/whatsapp/whatsapp.constant.ts @@ -0,0 +1,14 @@ +export const WHATSAPP_BUSINESS_API_URL = + process.env.WHATSAPP_BUSINESS_API_URL ?? 'https://graph.facebook.com/'; + +export const WHATSAPP_BUSINESS_VERSION = + process.env.WHATSAPP_BUSINESS_VERSION ?? 'v21.0'; + +export const WHATSAPP_BUSINESS_QUEUE_URL = + process.env.WHATSAPP_BUSINESS_QUEUE_URL ?? 'auth/login'; + +export const WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID = + process.env.WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID ?? ''; + +export const WHATSAPP_BUSINESS_ACCESS_TOKEN = + process.env.WHATSAPP_BUSINESS_ACCESS_TOKEN ?? ''; diff --git a/src/services/whatsapp/whatsapp.helper.ts b/src/services/whatsapp/whatsapp.helper.ts new file mode 100644 index 0000000..2429d0f --- /dev/null +++ b/src/services/whatsapp/whatsapp.helper.ts @@ -0,0 +1,62 @@ +export function getTextMessageInput(recipient, text) { + return JSON.stringify({ + messaging_product: 'whatsapp', + preview_url: false, + recipient_type: 'individual', + to: recipient, + type: 'text', + text: { + body: text, + }, + }); +} + +export function getTemplatedMessageInput(recipient, movie, seats) { + return JSON.stringify({ + messaging_product: 'whatsapp', + to: recipient, + type: 'template', + template: { + name: 'sample_movie_ticket_confirmation', + language: { + code: 'en_US', + }, + components: [ + { + type: 'header', + parameters: [ + { + type: 'image', + image: { + link: movie.thumbnail, + }, + }, + ], + }, + { + type: 'body', + parameters: [ + { + type: 'text', + text: movie.title, + }, + { + type: 'date_time', + date_time: { + fallback_value: movie.time, + }, + }, + { + type: 'text', + text: movie.venue, + }, + { + type: 'text', + text: seats, + }, + ], + }, + ], + }, + }); +} diff --git a/src/services/whatsapp/whatsapp.service.ts b/src/services/whatsapp/whatsapp.service.ts new file mode 100644 index 0000000..3328586 --- /dev/null +++ b/src/services/whatsapp/whatsapp.service.ts @@ -0,0 +1,158 @@ +import { + phoneNumberOnly, + toTime, +} from 'src/modules/queue/domain/helpers/time.helper'; +import { WhatsappQueue } from './entity/whatsapp-queue.entity'; +import { + WHATSAPP_BUSINESS_ACCESS_TOKEN, + WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID, + WHATSAPP_BUSINESS_API_URL, + WHATSAPP_BUSINESS_QUEUE_URL, + WHATSAPP_BUSINESS_VERSION, +} from './whatsapp.constant'; +import axios from 'axios'; +import { Logger } from '@nestjs/common'; + +export class WhatsappService { + async sendMessage(data) { + const config = { + method: 'post', + url: `${WHATSAPP_BUSINESS_API_URL}/${WHATSAPP_BUSINESS_VERSION}/${WHATSAPP_BUSINESS_ACCOUNT_NUMBER_ID}/messages`, + headers: { + Authorization: `Bearer ${WHATSAPP_BUSINESS_ACCESS_TOKEN}`, + 'Content-Type': 'application/json', + }, + data: data, + }; + + const response = await axios(config); + return response.data; + } + + async queueRegister(data: WhatsappQueue) { + const queueUrl = `${WHATSAPP_BUSINESS_QUEUE_URL}?id=${data.id}`; + const payload = { + messaging_product: 'whatsapp', + to: phoneNumberOnly(data.phone), // recipient's phone number + type: 'template', + template: { + name: 'queue_created', + language: { + code: 'id', // language code + }, + components: [ + { + type: 'header', + parameters: [ + { + parameter_name: 'queue_code', + type: 'text', + text: data.code, // replace with queue_code variable + }, + ], + }, + { + type: 'body', + parameters: [ + { + parameter_name: 'name', + type: 'text', + text: data.name, // replace with name variable + }, + { + parameter_name: 'item_name', + type: 'text', + text: data.item_name, // replace with item_name variable + }, + { + parameter_name: 'queue_code', + type: 'text', + text: data.code, // replace with queue_code variable + }, + { + parameter_name: 'queue_time', + type: 'text', + text: toTime(data.time), // replace with queue_time variable + }, + ], + }, + { + type: 'button', + sub_type: 'url', + index: '0', + parameters: [ + { + type: 'text', + text: queueUrl, // replace with dynamic URL + }, + ], + }, + ], + }, + }; + + await this.sendMessage(payload); + Logger.log(`Notification register for ${data.code} send to ${data.phone}`); + } + + async queueProcess(data: WhatsappQueue) { + const queueUrl = `${WHATSAPP_BUSINESS_QUEUE_URL}?id=${data.id}`; + const payload = { + messaging_product: 'whatsapp', + to: data.phone, // recipient's phone number + type: 'template', + template: { + name: 'queue_process', + language: { + code: 'id', // language code + }, + components: [ + { + type: 'header', + parameters: [ + { + parameter_name: 'queue_code', + type: 'text', + text: data.item_name, // replace with queue_code variable + }, + ], + }, + { + type: 'body', + parameters: [ + { + parameter_name: 'name', + type: 'text', + text: data.name, // replace with name variable + }, + { + parameter_name: 'queue_code', + type: 'text', + text: data.code, // replace with queue_code variable + }, + { + parameter_name: 'queue_time', + type: 'text', + text: toTime(data.time), // replace with queue_time variable + }, + ], + }, + { + type: 'button', + sub_type: 'url', + index: '0', + parameters: [ + { + type: 'text', + text: queueUrl, // replace with dynamic URL + }, + ], + }, + ], + }, + }; + + await this.sendMessage(payload); + Logger.log(`Notification process for ${data.code} send to ${data.phone}`); + } +} -- 2.40.1 From 66720c5b8be6b6e6c2bc3804a4abf0965e3af807 Mon Sep 17 00:00:00 2001 From: shancheas Date: Sat, 21 Dec 2024 05:20:25 +0700 Subject: [PATCH 3/4] feat: implement requiring call notification --- src/modules/queue/domain/queue-admin.orchestrator.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/modules/queue/domain/queue-admin.orchestrator.ts b/src/modules/queue/domain/queue-admin.orchestrator.ts index 96d6214..b08c796 100644 --- a/src/modules/queue/domain/queue-admin.orchestrator.ts +++ b/src/modules/queue/domain/queue-admin.orchestrator.ts @@ -57,12 +57,16 @@ export class QueueAdminOrchestrator { for (const queueItem of itemMasters) { const queueTimes = await this.queueTimeFormula.items(queueItem.id); + const call_preparation = queueItem.call_preparation * 60 * 1000; if (!queueItem.use_notification) continue; for (const queueId in queueTimes) { const callTime = queueTimes[queueId]; - if (timeIsBefore(currentTime, callTime, queueItem.call_preparation)) { + if ( + queueItem.requiring_notification || + timeIsBefore(currentTime, callTime, queueItem.call_preparation) + ) { const queueTicket = await this.service.queueTicket(queueId); const payload: WhatsappQueue = { id: queueId, @@ -76,11 +80,10 @@ export class QueueAdminOrchestrator { console.log({ currentTime: toTime(currentTime), callTime: toTime(callTime), - last_notification: toTime(queueTicket.last_notification), - queueId, + lastNotification: toTime(queueTicket.last_notification), + code: queueTicket.code, }); - const call_preparation = queueItem.call_preparation * 60 * 1000; if (queueTicket.last_notification < currentTime - call_preparation) { await notification.queueProcess(payload); this.service.updateLastNotification(queueId, currentTime); -- 2.40.1 From d7ed77934d5dbd32ff5c4b80b074be01b3084c67 Mon Sep 17 00:00:00 2001 From: shancheas Date: Sat, 21 Dec 2024 05:26:16 +0700 Subject: [PATCH 4/4] temp: remove log --- .../queue/domain/queue-admin.orchestrator.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/modules/queue/domain/queue-admin.orchestrator.ts b/src/modules/queue/domain/queue-admin.orchestrator.ts index b08c796..9bfc106 100644 --- a/src/modules/queue/domain/queue-admin.orchestrator.ts +++ b/src/modules/queue/domain/queue-admin.orchestrator.ts @@ -77,12 +77,14 @@ export class QueueAdminOrchestrator { time: callTime, }; - console.log({ - currentTime: toTime(currentTime), - callTime: toTime(callTime), - lastNotification: toTime(queueTicket.last_notification), - code: queueTicket.code, - }); + // console.table([ + // { + // code: queueTicket.code, + // currentTime: toTime(currentTime), + // callTime: toTime(callTime), + // lastNotification: toTime(queueTicket.last_notification), + // }, + // ]); if (queueTicket.last_notification < currentTime - call_preparation) { await notification.queueProcess(payload); -- 2.40.1