import { Injectable } from '@nestjs/common'; import * as moment from 'moment'; import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; import { TransactionUserType } from 'src/modules/transaction/transaction/constants'; import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model'; import { QueueBucketReadService } from '../../data/services/queue-bucket'; import { QueueService } from '../../data/services/queue.service'; import { TicketDataService } from '../../data/services/ticket.service'; import { RegisterQueueDto } from '../../infrastructure/controllers/dto/register-queue.dto'; import { QueueOrder } from '../entities/order.entity'; import { QueueItem } from '../entities/queue-item.entity'; import { QueueTicket } from '../entities/ticket.entity'; import { QueueTimeFormula } from './formula/queue-time.formula'; import { RegisterQueueManager } from './register-queue.manager'; import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; import { QueueModel } from '../../data/models/queue.model'; @Injectable() export class GenerateQueueManager { constructor( private readonly ticketService: TicketDataService, private readonly queueService: QueueService, private readonly bucketService: QueueBucketReadService, private readonly queueTimeFormula: QueueTimeFormula, ) {} async generate(transaction: TransactionModel) { const date = transaction.booking_date ?? transaction.invoice_date; const queue_date = moment(date, 'YYYY-MM-DD').unix(); const isToday = moment(date, 'YYYY-MM-DD').isSame(moment(), 'day'); const { id, customer_name, customer_phone, invoice_code } = transaction; const customerOrder = { code: invoice_code, customer: customer_name, phone: customer_phone, date: queue_date * 1000, transaction_id: id, }; const items = this.generateItems(transaction.items); const existTicket = isToday ? await this.ticketService.ticketByUser(customer_name, customer_phone) : null; const insertTickets: QueueTicket[] = []; if (customer_name && customer_phone && existTicket) { existTicket.items.push(...items); await this.ticketService.updateQueueTicket(existTicket); existTicket.items = items; insertTickets.push(existTicket); } else { const ticket: QueueTicket = { ...customerOrder, items }; const order: QueueOrder = { ...customerOrder, tickets: [ticket] }; const queueOrder = await this.ticketService.createQueueOrder(order); insertTickets.push(...queueOrder.tickets); } const results: QueueModel[] = []; const vipCustomer = transaction.customer_category?.has_vip_pass || transaction.customer_type === TransactionUserType.VIP; if (vipCustomer || transaction.creator_counter_no != null) { for (const ticket of insertTickets) { const ticket_id = ticket.id; const items = {}; ticket.items.forEach((item) => { const item_id = item['item_queue_id']; const currentItem = items[item_id]; if (currentItem) { currentItem.qty += item.qty; } items[item_id] = currentItem ? currentItem : { item_id, ticket_id, qty: item.qty, }; }); for (const payload of Object.values(items)) { const isVip = vipCustomer || transaction.creator_counter_no == null; const result = await this.create(payload as any, isVip); results.push(result); } } } return results; } generateItems(items: TransactionItemModel[]): QueueItem[] { const transactionItems = []; items.forEach((item) => { if (item.item.use_queue) { transactionItems.push({ item_queue_id: item.item.item_queue_id, item_id: item.item_id, qty: item.qty, }); } if (item.item.bundling_items.length > 0) { item.item.bundling_items.forEach((bundling_item) => { if (bundling_item.use_queue) { transactionItems.push({ item_queue_id: bundling_item.item_queue_id, item_id: bundling_item.id, qty: item.qty, }); } }); } }); return this.mergeQueueItems(transactionItems); } mergeQueueItems(arr) { const result = {}; arr.forEach((item) => { if (result[item.item_id]) { result[item.item_id].qty += item.qty; } else { result[item.item_id] = { ...item }; } }); return Object.values(result); } async create(data: RegisterQueueDto, isVip = false): Promise { const queue = await this.queueService.getTicketItems( data.ticket_id, data.item_id, ); const queueRequest: any = { qty: data.qty, item_id: queue.id, vip: isVip, }; const registerQueueManager = new RegisterQueueManager( this.bucketService, this.queueTimeFormula, ); registerQueueManager.setData(queueRequest); registerQueueManager.setService(this.queueService, TABLE_NAME.QUEUE); await registerQueueManager.execute(); const result = await registerQueueManager.getResult(); result.time = null; return result; } }