import { Injectable, UnauthorizedException } from '@nestjs/common'; import { TicketDataService } from '../data/services/ticket.service'; import { QueueOrder } from './entities/order.entity'; import { Queue } from './entities/queue.entity'; import { QueueDataService, QueueOrderService, QueueService, } from '../data/services/queue.service'; import { RegisterQueueManager } from './usecases/register-queue.manager'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; import { RegisterQueueDto } from '../infrastructure/controllers/dto/register-queue.dto'; import { CustomerQueueSummaryManager } from './usecases/queue/customer-queue-summary.manager'; import { CustomerQueueDetailManager } from './usecases/queue/customer-queue-detail.manager'; import { CustomerQueueItemManager } from './usecases/queue/customer-queue-item.manager'; import { CustomerQueueItemListManager } from './usecases/queue/customer-queue-item-list.manager'; import { CustomerQueueListManager } from './usecases/queue/customer-queue-list.manager'; import { SplitQueueDto } from '../infrastructure/controllers/dto/split-queue.dto'; import { SplitQueueManager } from './usecases/split-queue.manager'; import { LoginQueueDto } from '../infrastructure/controllers/dto/login-queue.dto'; 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 { QueueOrderModel, QueueTicketModel } from '../data/models/queue.model'; import { CustomerQueueRecommendManager } from './usecases/queue/customer-queue-recommend.manager'; @Injectable() export class QueueOrchestrator { constructor( public readonly dataService: TicketDataService, public readonly transactionService: TransactionDataService, private readonly queueService: QueueService, private readonly queueOrderService: QueueOrderService, private readonly registerQueueManager: RegisterQueueManager, private readonly splitQueueManager: SplitQueueManager, private readonly queueDataService: QueueDataService, ) {} async loginCustomer(id: string): Promise { try { const order = await this.dataService.loginQueue(id); const code = order.tickets[0].code ?? order.code; const tickets = await this.dataService.ticketByCode(code); order.tickets = tickets; return order; } catch (error) { throw new UnauthorizedException({ message: 'Invoice tidak ditemukan', error: 'INVOICE_NOT_FOUND', }); } } async loginPhone(login: LoginQueueDto): Promise { const { name, phone } = login; const now = moment().format('DD/MM/YYYY'); try { const order = await this.dataService.loginPhone(name, phone); const code = order.tickets[0].code ?? order.code; const tickets = await this.dataService.ticketByCode(code); order.tickets = tickets; return order; } catch (error) { throw new UnauthorizedException({ message: `Antrian atas nama ${name} dan nomor telepon ${phone} pada tanggal ${now} tidak ditemukan`, error: 'INVOICE_NOT_FOUND', }); } } async create(data: RegisterQueueDto): Promise { const queue = await this.queueService.getTicketItems( data.ticket_id, data.item_id, ); const queueRequest: any = { qty: data.qty, item_id: queue.id, }; this.registerQueueManager.setData(queueRequest); this.registerQueueManager.setService(this.queueService, TABLE_NAME.QUEUE); await this.registerQueueManager.execute(); return this.registerQueueManager.getResult(); } async split(data: SplitQueueDto): Promise { const queueIds = data.items.map((i) => i.queue_item_id); const queue = await this.dataService.orderItems(data.order_id, queueIds); const existTicket = await this.dataService.ticketByUser( data.name, data.phone, ); if (existTicket) { const itemTickets = this.itemsFromOrder(queue); const items = data.items.map((item) => { const item_id = itemTickets[item.queue_item_id]; return { item_queue_id: item_id, item_id: item_id, qty: item.qty, }; }); existTicket.items.push(...items); await this.dataService.updateQueueTicket(existTicket); data.items.forEach((item) => { this.queueService.updateItemQty(item.queue_item_id, item.qty); }); return queue; } this.splitQueueManager.setRequestData(data); this.splitQueueManager.setData(queue); this.splitQueueManager.setService( this.queueOrderService, TABLE_NAME.QUEUE_ORDER, ); await this.splitQueueManager.execute(); return this.splitQueueManager.getResult(); } itemsFromOrder(order: QueueOrderModel) { const itemTickets = {}; order.tickets.forEach((ticket) => { ticket.items.forEach((item) => { itemTickets[item.id] = item.item_id; }); }); return itemTickets; } async queuePOSTickets(order_id: string): Promise { const tickets = await this.dataService.queuePosTickets(order_id); const manager = new CustomerQueuePosItemManager(tickets); return manager.data; } async queueTickets(order_id: string): Promise { const tickets = await this.dataService.queueTickets(order_id); const manager = new CustomerQueueSummaryManager(tickets); return manager.data; } async queueTicketDetail(order_id: string, ticket_id: string): Promise { const tickets = await this.dataService.queueTicketItems( 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; } async queueTicketSummary(order_id: string, ticket_id: string): Promise { const tickets = await this.dataService.queueTicketActive( order_id, ticket_id, ); const manager = new CustomerQueueTicketSummaryManager(tickets); return manager.data; } async queueItemDetail(order_id: string, item_id: string): Promise { const tickets = await this.dataService.queueItemTickets(order_id, item_id); const manager = new CustomerQueueItemManager(tickets); return manager.data; } async queueItemRecommendation(order_id: string): Promise { const tickets = await this.dataService.queueTickets(order_id); const queueItemIds = this.getQueueItemFromTickets(tickets); const recommendItems = await this.queueDataService.exclude(queueItemIds); const recommendIds = recommendItems.map((item) => item.id); const queues = await this.queueService.queues(recommendIds); const manager = new CustomerQueueRecommendManager(tickets); manager.currentQueues(queues); return manager.recommend(recommendItems); } async queueItemSummary(): Promise { const recommendItems = await this.queueDataService.allQueue(); const recommendIds = recommendItems.map((item) => item.id); const queues = await this.queueService.queues(recommendIds); const manager = new CustomerQueueRecommendManager(null); manager.currentQueues(queues); return manager.recommend(recommendItems); } 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; } async queueUniqueItems(order_id: string): Promise { const tickets = await this.dataService.queueUniqueTickets(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; } async queueOrderItems(order_id: string): Promise { const tickets = await this.dataService.queueTickets(order_id); 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(); } }