feat: create queue using API
parent
187555a543
commit
3ace59c450
|
@ -22,8 +22,13 @@ 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 {
|
||||
QueueModel,
|
||||
QueueOrderModel,
|
||||
QueueTicketModel,
|
||||
} from '../data/models/queue.model';
|
||||
import { CustomerQueueRecommendManager } from './usecases/queue/customer-queue-recommend.manager';
|
||||
import { GenerateQueueManager } from './usecases/generate-queue.manager';
|
||||
|
||||
@Injectable()
|
||||
export class QueueOrchestrator {
|
||||
|
@ -35,8 +40,13 @@ export class QueueOrchestrator {
|
|||
private readonly registerQueueManager: RegisterQueueManager,
|
||||
private readonly splitQueueManager: SplitQueueManager,
|
||||
private readonly queueDataService: QueueDataService,
|
||||
private readonly generateQueueManager: GenerateQueueManager,
|
||||
) {}
|
||||
|
||||
async generate(data: any): Promise<QueueModel[]> {
|
||||
return await this.generateQueueManager.generate(data);
|
||||
}
|
||||
|
||||
async loginCustomer(id: string): Promise<QueueOrder> {
|
||||
try {
|
||||
const order = await this.dataService.loginQueue(id);
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import 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 { 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 = await this.ticketService.ticketByUser(
|
||||
customer_name,
|
||||
customer_phone,
|
||||
);
|
||||
|
||||
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[] = [];
|
||||
if (
|
||||
transaction.customer_category?.has_vip_pass ||
|
||||
transaction.customer_type === TransactionUserType.VIP
|
||||
) {
|
||||
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 result = await this.create(payload as any);
|
||||
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<QueueItem>(result);
|
||||
}
|
||||
|
||||
async create(data: RegisterQueueDto): Promise<QueueModel> {
|
||||
const queue = await this.queueService.getTicketItems(
|
||||
data.ticket_id,
|
||||
data.item_id,
|
||||
);
|
||||
const queueRequest: any = {
|
||||
qty: data.qty,
|
||||
item_id: queue.id,
|
||||
vip: true,
|
||||
};
|
||||
const registerQueueManager = new RegisterQueueManager(
|
||||
this.bucketService,
|
||||
this.queueTimeFormula,
|
||||
);
|
||||
registerQueueManager.setData(queueRequest);
|
||||
registerQueueManager.setService(this.queueService, TABLE_NAME.QUEUE);
|
||||
await registerQueueManager.execute();
|
||||
|
||||
return registerQueueManager.getResult();
|
||||
}
|
||||
}
|
|
@ -11,6 +11,9 @@ import { RegisterQueueDto } from './dto/register-queue.dto';
|
|||
import { SplitQueueDto } from './dto/split-queue.dto';
|
||||
import { LoginQueueDto } from './dto/login-queue.dto';
|
||||
import { LoginReceiptDto } from './dto/login-receipt.dto';
|
||||
import { mappingRevertTransaction } from 'src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper';
|
||||
import { TransactionType } from 'src/modules/transaction/transaction/constants';
|
||||
import { QueueModel } from '../../data/models/queue.model';
|
||||
|
||||
@ApiTags(`Queue`)
|
||||
@Controller(`v1/${MODULE_NAME.QUEUE}`)
|
||||
|
@ -19,6 +22,12 @@ import { LoginReceiptDto } from './dto/login-receipt.dto';
|
|||
export class QueueController {
|
||||
constructor(private orchestrator: QueueOrchestrator) {}
|
||||
|
||||
@Post('generate')
|
||||
async generateQueue(@Body() data: any): Promise<QueueModel[]> {
|
||||
mappingRevertTransaction(data, TransactionType.COUNTER);
|
||||
return await this.orchestrator.generate(data);
|
||||
}
|
||||
|
||||
@Post('register')
|
||||
async registerQueue(@Body() data: RegisterQueueDto): Promise<Queue> {
|
||||
return await this.orchestrator.create(data);
|
||||
|
|
|
@ -4,19 +4,7 @@ import {
|
|||
TransactionChangeStatusEvent,
|
||||
TransactionCreateQueueEvent,
|
||||
} from 'src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event';
|
||||
import { TicketDataService } from '../../data/services/ticket.service';
|
||||
import { QueueOrder } from '../../domain/entities/order.entity';
|
||||
import { QueueTicket } from '../../domain/entities/ticket.entity';
|
||||
import { QueueItem } from '../../domain/entities/queue-item.entity';
|
||||
import * as moment from 'moment';
|
||||
import { TransactionUserType } from 'src/modules/transaction/transaction/constants';
|
||||
import { RegisterQueueManager } from '../../domain/usecases/register-queue.manager';
|
||||
import { RegisterQueueDto } from '../controllers/dto/register-queue.dto';
|
||||
import { QueueService } from '../../data/services/queue.service';
|
||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||
import { QueueBucketReadService } from '../../data/services/queue-bucket';
|
||||
import { QueueTimeFormula } from '../../domain/usecases/formula/queue-time.formula';
|
||||
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
|
||||
import { GenerateQueueManager } from '../../domain/usecases/generate-queue.manager';
|
||||
|
||||
@EventsHandler(TransactionChangeStatusEvent, TransactionCreateQueueEvent)
|
||||
export class QueueTransactionHandler
|
||||
|
@ -24,10 +12,7 @@ export class QueueTransactionHandler
|
|||
{
|
||||
constructor(
|
||||
private readonly dataService: TransactionDataService,
|
||||
private readonly ticketService: TicketDataService,
|
||||
private readonly queueService: QueueService,
|
||||
private readonly bucketService: QueueBucketReadService,
|
||||
private readonly queueTimeFormula: QueueTimeFormula,
|
||||
private readonly queueGenerateManager: GenerateQueueManager,
|
||||
) {}
|
||||
|
||||
async handle(event: TransactionChangeStatusEvent) {
|
||||
|
@ -50,127 +35,6 @@ export class QueueTransactionHandler
|
|||
],
|
||||
});
|
||||
|
||||
const date = transaction.booking_date ?? transaction.invoice_date;
|
||||
const queue_date = moment(date, 'YYYY-MM-DD').unix();
|
||||
|
||||
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 = await this.ticketService.ticketByUser(
|
||||
customer_name,
|
||||
customer_phone,
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (
|
||||
transaction.customer_category?.has_vip_pass ||
|
||||
transaction.customer_type === TransactionUserType.VIP
|
||||
) {
|
||||
insertTickets.forEach((ticket) => {
|
||||
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,
|
||||
};
|
||||
});
|
||||
|
||||
Object.values(items).forEach((payload: any) => {
|
||||
this.create(payload);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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<QueueItem>(result);
|
||||
}
|
||||
|
||||
async create(data: RegisterQueueDto): Promise<void> {
|
||||
const queue = await this.queueService.getTicketItems(
|
||||
data.ticket_id,
|
||||
data.item_id,
|
||||
);
|
||||
const queueRequest: any = {
|
||||
qty: data.qty,
|
||||
item_id: queue.id,
|
||||
vip: true,
|
||||
};
|
||||
const registerQueueManager = new RegisterQueueManager(
|
||||
this.bucketService,
|
||||
this.queueTimeFormula,
|
||||
);
|
||||
registerQueueManager.setData(queueRequest);
|
||||
registerQueueManager.setService(this.queueService, TABLE_NAME.QUEUE);
|
||||
await registerQueueManager.execute();
|
||||
await this.queueGenerateManager.generate(transaction);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import { QueueTransactionCancelHandler } from './infrastructure/handlers/cancel-
|
|||
import { ItemQueueModel } from '../item-related/item-queue/data/models/item-queue.model';
|
||||
import { QueueTimeFormula } from './domain/usecases/formula/queue-time.formula';
|
||||
import { QueueJobController } from './infrastructure/controllers/queue-job.controller';
|
||||
import { GenerateQueueManager } from './domain/usecases/generate-queue.manager';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -79,6 +80,7 @@ import { QueueJobController } from './infrastructure/controllers/queue-job.contr
|
|||
SplitQueueManager,
|
||||
|
||||
QueueTimeFormula,
|
||||
GenerateQueueManager,
|
||||
],
|
||||
})
|
||||
export class QueueModule {}
|
||||
|
|
Loading…
Reference in New Issue