feat: add average item queue time
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details

pull/115/head 1.2.2-alpha.1
shancheas 2024-11-14 10:06:51 +07:00
parent e9535749d4
commit 2b132c53a8
7 changed files with 74 additions and 12 deletions

View File

@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddItemQueueToQueue1731498661938 implements MigrationInterface {
name = 'AddItemQueueToQueue1731498661938';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "queues" ADD "item_queue_id" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "queues" DROP COLUMN "item_queue_id"`);
}
}

View File

@ -131,6 +131,9 @@ export class QueueModel extends BaseModel<Queue> implements Queue {
@Column('varchar') @Column('varchar')
item_id: string; item_id: string;
@Column('varchar', { nullable: true })
item_queue_id: string;
@Column('int') @Column('int')
qty: number; qty: number;
} }

View File

@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { DataSource, In, Repository } from 'typeorm'; import { Between, DataSource, In, Repository } from 'typeorm';
import { import {
QueueItemModel, QueueItemModel,
QueueModel, QueueModel,
@ -10,6 +10,7 @@ import {
} from '../models/queue.model'; } from '../models/queue.model';
import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; import { BaseReadService } from 'src/core/modules/data/service/base-read.service';
import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
import * as moment from 'moment';
@Injectable() @Injectable()
export class QueueDataService extends BaseReadService<QueueModel> { export class QueueDataService extends BaseReadService<QueueModel> {
@ -48,6 +49,20 @@ export class QueueService extends BaseDataService<QueueModel> {
super(repo); 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) { async getTicketItems(ticket_id: string, item_id: string) {
return this.item.findOneOrFail({ return this.item.findOneOrFail({
relations: ['item'], relations: ['item'],

View File

@ -133,6 +133,8 @@ export class TicketDataService extends BaseDataService<QueueTicket> {
async queueTickets(order_id: string): Promise<QueueTicketModel[]> { async queueTickets(order_id: string): Promise<QueueTicketModel[]> {
const order = await this.orderIds(order_id); const order = await this.orderIds(order_id);
const start = moment().startOf('day').valueOf();
const end = moment().endOf('day').valueOf();
return this.repo.find({ return this.repo.find({
relations: [ relations: [
'items', 'items',
@ -142,6 +144,7 @@ export class TicketDataService extends BaseDataService<QueueTicket> {
], ],
where: { where: {
order_id: In(order), order_id: In(order),
date: Between(start, end),
}, },
}); });
} }

View File

@ -21,6 +21,7 @@ import * as moment from 'moment';
import { CustomerQueueTicketSummaryManager } from './usecases/queue/customer-queue-ticket.manager'; import { CustomerQueueTicketSummaryManager } from './usecases/queue/customer-queue-ticket.manager';
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service'; import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
import { CustomerQueuePosItemManager } from './usecases/queue/customer-queue-pos-item.manager'; import { CustomerQueuePosItemManager } from './usecases/queue/customer-queue-pos-item.manager';
import { QueueTicketModel } from '../data/models/queue.model';
@Injectable() @Injectable()
export class QueueOrchestrator { export class QueueOrchestrator {
@ -103,7 +104,11 @@ export class QueueOrchestrator {
order_id, order_id,
ticket_id, ticket_id,
); );
const queueItemIds = this.getQueueItemFromTickets(tickets);
const queues = await this.queueService.queues(queueItemIds);
const manager = new CustomerQueueDetailManager(tickets); const manager = new CustomerQueueDetailManager(tickets);
manager.currentQueues(queues);
return manager.data; return manager.data;
} }
@ -125,7 +130,10 @@ export class QueueOrchestrator {
async queueItems(order_id: string): Promise<any> { async queueItems(order_id: string): Promise<any> {
const tickets = await this.dataService.queueTickets(order_id); 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); const manager = new CustomerQueueItemListManager(tickets);
manager.currentQueues(queues);
return manager.data; return manager.data;
} }
@ -134,4 +142,14 @@ export class QueueOrchestrator {
const manager = new CustomerQueueListManager(tickets); const manager = new CustomerQueueListManager(tickets);
return manager.data; 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();
}
} }

View File

@ -6,7 +6,7 @@ export class QueueCondition {
private ticketItems = {}; private ticketItems = {};
constructor(readonly items: QueueModel[]) { constructor(readonly items: QueueModel[]) {
items.forEach((item) => { 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]; const currentItem = this.ticketItems[item_id];
this.ticketItems[item_id] = currentItem ? [...currentItem, item] : [item]; this.ticketItems[item_id] = currentItem ? [...currentItem, item] : [item];
}); });
@ -14,14 +14,17 @@ export class QueueCondition {
condition(item_id: string) { condition(item_id: string) {
const queues: QueueModel[] = this.ticketItems[item_id] ?? []; const queues: QueueModel[] = this.ticketItems[item_id] ?? [];
const time = queues[0]?.time; const time = queues[0];
const nearest = time ? toTime(time) : 0; const nearest = time ? toTime(time.time) : 0;
const last = [...queues].pop();
const lastTime = last ? toTime(last.time) : 0;
return { return {
available: queues.length == 0, available: queues.length == 0,
average: this.averageTime(queues), average: this.averageTime(queues),
nearest: nearest, nearest: nearest,
crowded_level: queues.length, crowded_level: queues.length,
available_time: nearest, available_time: lastTime,
}; };
} }

View File

@ -6,9 +6,10 @@ import {
} from 'src/core/strings/constants/interface.constants'; } from 'src/core/strings/constants/interface.constants';
import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager';
import { STATUS } from 'src/core/strings/constants/base.constants'; 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 { padCode } from 'src/modules/transaction/vip-code/domain/usecases/managers/helpers/generate-random.helper';
import { QueueBucketReadService } from '../../data/services/queue-bucket'; import { QueueBucketReadService } from '../../data/services/queue-bucket';
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
@Injectable() @Injectable()
export class RegisterQueueManager extends BaseCreateManager<QueueModel> { export class RegisterQueueManager extends BaseCreateManager<QueueModel> {
@ -17,12 +18,13 @@ export class RegisterQueueManager extends BaseCreateManager<QueueModel> {
} }
async averageTime(): Promise<number> { async averageTime(): Promise<number> {
const item = await this.getItem(); const item = await this.getItemMaster();
return item.item.item.play_estimation; return item.play_estimation;
} }
async beforeProcess(): Promise<void> { async beforeProcess(): Promise<void> {
const vip = this.data.vip ?? false; const vip = this.data.vip ?? false;
const item = await this.getItemMaster();
const queueNumber = await this.bucketService.getQueue( const queueNumber = await this.bucketService.getQueue(
this.data.item_id, this.data.item_id,
vip, vip,
@ -33,19 +35,22 @@ export class RegisterQueueManager extends BaseCreateManager<QueueModel> {
Object.assign(this.data, { Object.assign(this.data, {
status: STATUS.WAITING, status: STATUS.WAITING,
time: new Date().getTime(), time: new Date().getTime(),
item_queue_id: item.item_queue_id,
vip, vip,
code, code,
}); });
return; return;
} }
async getItem(): Promise<QueueModel> { async getItemMaster(): Promise<ItemModel> {
return this.dataService.repo.findOne({ const queueItem: QueueItemModel = await this.dataService.item.findOne({
relations: ['item', 'item.item'], relations: ['item'],
where: { where: {
item_id: this.data.item_id, id: this.data.item_id,
}, },
}); });
return queueItem.item;
} }
async afterProcess(): Promise<void> { async afterProcess(): Promise<void> {