From 2b132c53a840e7c3052d5e477589e2f1e47a7e78 Mon Sep 17 00:00:00 2001 From: shancheas Date: Thu, 14 Nov 2024 10:06:51 +0700 Subject: [PATCH] feat: add average item queue time --- .../1731498661938-add-item-queue-to-queue.ts | 15 +++++++++++++++ src/modules/queue/data/models/queue.model.ts | 3 +++ .../queue/data/services/queue.service.ts | 17 ++++++++++++++++- .../queue/data/services/ticket.service.ts | 3 +++ .../queue/domain/queue.orchestrator.ts | 18 ++++++++++++++++++ .../formula/queue-condition.formula.ts | 11 +++++++---- .../domain/usecases/register-queue.manager.ts | 19 ++++++++++++------- 7 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 src/database/migrations/1731498661938-add-item-queue-to-queue.ts diff --git a/src/database/migrations/1731498661938-add-item-queue-to-queue.ts b/src/database/migrations/1731498661938-add-item-queue-to-queue.ts new file mode 100644 index 0000000..a1151af --- /dev/null +++ b/src/database/migrations/1731498661938-add-item-queue-to-queue.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddItemQueueToQueue1731498661938 implements MigrationInterface { + name = 'AddItemQueueToQueue1731498661938'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "queues" ADD "item_queue_id" character varying`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "queues" DROP COLUMN "item_queue_id"`); + } +} diff --git a/src/modules/queue/data/models/queue.model.ts b/src/modules/queue/data/models/queue.model.ts index 04ba717..ec2083f 100644 --- a/src/modules/queue/data/models/queue.model.ts +++ b/src/modules/queue/data/models/queue.model.ts @@ -131,6 +131,9 @@ export class QueueModel extends BaseModel implements Queue { @Column('varchar') item_id: string; + @Column('varchar', { nullable: true }) + item_queue_id: string; + @Column('int') qty: number; } diff --git a/src/modules/queue/data/services/queue.service.ts b/src/modules/queue/data/services/queue.service.ts index 7efe003..fb34c5d 100644 --- a/src/modules/queue/data/services/queue.service.ts +++ b/src/modules/queue/data/services/queue.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; -import { DataSource, In, Repository } from 'typeorm'; +import { Between, DataSource, In, Repository } from 'typeorm'; import { QueueItemModel, QueueModel, @@ -10,6 +10,7 @@ import { } from '../models/queue.model'; import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; +import * as moment from 'moment'; @Injectable() export class QueueDataService extends BaseReadService { @@ -48,6 +49,20 @@ export class QueueService extends BaseDataService { super(repo); } + async queues(ids: string[]) { + const start = moment().startOf('day').valueOf(); + const end = moment().endOf('day').valueOf(); + return this.repo.find({ + where: { + item_queue_id: In(ids), + time: Between(start, end), + }, + order: { + time: 'ASC', + }, + }); + } + async getTicketItems(ticket_id: string, item_id: string) { return this.item.findOneOrFail({ relations: ['item'], diff --git a/src/modules/queue/data/services/ticket.service.ts b/src/modules/queue/data/services/ticket.service.ts index e14150d..36255de 100644 --- a/src/modules/queue/data/services/ticket.service.ts +++ b/src/modules/queue/data/services/ticket.service.ts @@ -133,6 +133,8 @@ export class TicketDataService extends BaseDataService { async queueTickets(order_id: string): Promise { const order = await this.orderIds(order_id); + const start = moment().startOf('day').valueOf(); + const end = moment().endOf('day').valueOf(); return this.repo.find({ relations: [ 'items', @@ -142,6 +144,7 @@ export class TicketDataService extends BaseDataService { ], where: { order_id: In(order), + date: Between(start, end), }, }); } diff --git a/src/modules/queue/domain/queue.orchestrator.ts b/src/modules/queue/domain/queue.orchestrator.ts index 660d5e2..87796d8 100644 --- a/src/modules/queue/domain/queue.orchestrator.ts +++ b/src/modules/queue/domain/queue.orchestrator.ts @@ -21,6 +21,7 @@ import * as moment from 'moment'; import { CustomerQueueTicketSummaryManager } from './usecases/queue/customer-queue-ticket.manager'; import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service'; import { CustomerQueuePosItemManager } from './usecases/queue/customer-queue-pos-item.manager'; +import { QueueTicketModel } from '../data/models/queue.model'; @Injectable() export class QueueOrchestrator { @@ -103,7 +104,11 @@ export class QueueOrchestrator { order_id, ticket_id, ); + + const queueItemIds = this.getQueueItemFromTickets(tickets); + const queues = await this.queueService.queues(queueItemIds); const manager = new CustomerQueueDetailManager(tickets); + manager.currentQueues(queues); return manager.data; } @@ -125,7 +130,10 @@ export class QueueOrchestrator { async queueItems(order_id: string): Promise { const tickets = await this.dataService.queueTickets(order_id); + const queueItemIds = this.getQueueItemFromTickets(tickets); + const queues = await this.queueService.queues(queueItemIds); const manager = new CustomerQueueItemListManager(tickets); + manager.currentQueues(queues); return manager.data; } @@ -134,4 +142,14 @@ export class QueueOrchestrator { const manager = new CustomerQueueListManager(tickets); return manager.data; } + + getQueueItemFromTickets(tickets: QueueTicketModel[]) { + const queueItemIds = tickets.map((ticket) => { + return ticket.items.map((item) => { + return item.item.item_queue_id; + }); + }); + + return queueItemIds.flat(); + } } diff --git a/src/modules/queue/domain/usecases/formula/queue-condition.formula.ts b/src/modules/queue/domain/usecases/formula/queue-condition.formula.ts index 358f548..bf64da0 100644 --- a/src/modules/queue/domain/usecases/formula/queue-condition.formula.ts +++ b/src/modules/queue/domain/usecases/formula/queue-condition.formula.ts @@ -6,7 +6,7 @@ export class QueueCondition { private ticketItems = {}; constructor(readonly items: QueueModel[]) { items.forEach((item) => { - const item_id = item.item.item.item_queue?.id ?? item.item.item.id; + const item_id = item.item_queue_id; const currentItem = this.ticketItems[item_id]; this.ticketItems[item_id] = currentItem ? [...currentItem, item] : [item]; }); @@ -14,14 +14,17 @@ export class QueueCondition { condition(item_id: string) { const queues: QueueModel[] = this.ticketItems[item_id] ?? []; - const time = queues[0]?.time; - const nearest = time ? toTime(time) : 0; + const time = queues[0]; + const nearest = time ? toTime(time.time) : 0; + + const last = [...queues].pop(); + const lastTime = last ? toTime(last.time) : 0; return { available: queues.length == 0, average: this.averageTime(queues), nearest: nearest, crowded_level: queues.length, - available_time: nearest, + available_time: lastTime, }; } diff --git a/src/modules/queue/domain/usecases/register-queue.manager.ts b/src/modules/queue/domain/usecases/register-queue.manager.ts index 29d4537..10176bd 100644 --- a/src/modules/queue/domain/usecases/register-queue.manager.ts +++ b/src/modules/queue/domain/usecases/register-queue.manager.ts @@ -6,9 +6,10 @@ import { } from 'src/core/strings/constants/interface.constants'; import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; import { STATUS } from 'src/core/strings/constants/base.constants'; -import { QueueModel } from '../../data/models/queue.model'; +import { QueueItemModel, QueueModel } from '../../data/models/queue.model'; import { padCode } from 'src/modules/transaction/vip-code/domain/usecases/managers/helpers/generate-random.helper'; import { QueueBucketReadService } from '../../data/services/queue-bucket'; +import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; @Injectable() export class RegisterQueueManager extends BaseCreateManager { @@ -17,12 +18,13 @@ export class RegisterQueueManager extends BaseCreateManager { } async averageTime(): Promise { - const item = await this.getItem(); - return item.item.item.play_estimation; + const item = await this.getItemMaster(); + return item.play_estimation; } async beforeProcess(): Promise { const vip = this.data.vip ?? false; + const item = await this.getItemMaster(); const queueNumber = await this.bucketService.getQueue( this.data.item_id, vip, @@ -33,19 +35,22 @@ export class RegisterQueueManager extends BaseCreateManager { Object.assign(this.data, { status: STATUS.WAITING, time: new Date().getTime(), + item_queue_id: item.item_queue_id, vip, code, }); return; } - async getItem(): Promise { - return this.dataService.repo.findOne({ - relations: ['item', 'item.item'], + async getItemMaster(): Promise { + const queueItem: QueueItemModel = await this.dataService.item.findOne({ + relations: ['item'], where: { - item_id: this.data.item_id, + id: this.data.item_id, }, }); + + return queueItem.item; } async afterProcess(): Promise {