import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; import { Between, DataSource, In, Not, Repository } from 'typeorm'; import { QueueItemModel, QueueModel, QueueOrderModel, } 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 { ItemQueueModel } from 'src/modules/item-related/item-queue/data/models/item-queue.model'; import * as moment from 'moment'; import * as math from 'mathjs'; import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; @Injectable() export class QueueDataService extends BaseReadService { constructor( @InjectRepository(QueueModel, CONNECTION_NAME.DEFAULT) private repo: Repository, @InjectRepository(ItemQueueModel, CONNECTION_NAME.DEFAULT) private itemQueueRepo: Repository, ) { super(repo); } async waitingQueue(item_queue_id: string) { const start = moment().startOf('day').valueOf(); const end = moment().endOf('day').valueOf(); return this.repo.find({ where: { time: Between(start, end), item_queue_id, status: 'waiting', }, order: { time: 'ASC', }, }); } async doneQueue(item_queue_id: string) { const start = moment().startOf('day').valueOf(); const end = moment().endOf('day').valueOf(); return this.repo.find({ where: { time: Between(start, end), item_queue_id, status: In(['done', 'called']), }, order: { time: 'ASC', }, }); } async exclude(item_queue_id: string[]) { const queues = await this.itemQueueRepo.find({ relations: ['items'], where: { id: Not(In(item_queue_id)), }, }); return queues.filter((q) => q.items.length > 0); } async lastQueue(item_queue_id: string) { const start = moment().startOf('day').valueOf(); const end = moment().endOf('day').valueOf(); return this.repo.findOne({ where: { time: Between(start, end), item_queue_id, status: 'called', }, order: { call_time: 'DESC', }, }); } /** * @deprecated * Change to QueueTimeFormula (queue-time.formula.ts) * @param item_queue_id * @returns */ async queueTimes(item_queue_id: string): Promise { const queueTimes = {}; let now = moment().valueOf(); const itemQueue = await this.itemQueueRepo.findOne({ relations: ['items'], where: { id: item_queue_id, }, }); const times = itemQueue.items.map((item) => item.play_estimation ?? 0); const average = math.mean(times) * 60 * 1000; // change average minute to milliseconds const queues = await this.repo.find({ where: { item_queue_id, status: 'waiting', }, }); queueTimes[queues[0].id] = now; // first queue will be now for (let i = 1; i < queues.length; i++) { const queue = queues[i]; // duration will be total qty multiple by average const duration = queue.qty * average; // time to call will be now + duration const time = now + duration; queueTimes[queue.id] = time; // update now to last call time now = time; } return queueTimes; } async queueItems(item_queue_id: string[]): Promise { return this.repo.find({ relations: ['item', 'item.item', 'item.item.item_queue'], where: { item: { item: { item_queue: { id: In(item_queue_id) } } }, }, order: { time: 'DESC', }, }); } } @Injectable() export class QueueService extends BaseDataService { constructor( @InjectRepository(QueueModel, CONNECTION_NAME.DEFAULT) private repo: Repository, @InjectRepository(QueueItemModel, CONNECTION_NAME.DEFAULT) private item: Repository, @InjectRepository(ItemModel, CONNECTION_NAME.DEFAULT) private itemMaster: Repository, @InjectDataSource(CONNECTION_NAME.DEFAULT) private dataSource: DataSource, ) { super(repo); } async queues(ids: string[]) { const start = moment().startOf('day').valueOf(); const end = moment().endOf('day').valueOf(); const playEstimations = {}; for (const id of ids) { playEstimations[id] = await this.itemAverageTimeEstimation(id); } const queues = await this.repo.find({ where: { item_queue_id: In(ids), time: Between(start, end), }, order: { time: 'ASC', }, }); queues.forEach((queue) => { queue.average = playEstimations[queue.item_queue_id]; }); return queues; } async itemAverageTimeEstimation(item_queue_id: string) { const items = await this.itemMaster.find({ where: { item_queue_id, }, }); const times = items.map((item) => item.play_estimation ?? 0); const average = times.length > 0 ? math.mean(times) * 60 * 1000 : 0; // change average minute to milliseconds return average; } async getTicketItems(ticket_id: string, item_id: string) { return this.item.findOneOrFail({ relations: ['item'], where: [ { ticket_id, item_id, }, { ticket_id, item: { item_queue_id: item_id }, }, ], }); } 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); } } @Injectable() export class QueueOrderService extends BaseDataService { constructor( @InjectRepository(QueueOrderModel, CONNECTION_NAME.DEFAULT) private repo: Repository, ) { super(repo); } }