avicenna/service/data-hub/data-connector/src/modules/app-ticket-system/tickets.service.ts

113 lines
3.3 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
import { Ticket, TicketValidationState, Tour } from '@prisma/client';
import { Interval } from 'date-fns';
import { PubSub } from 'graphql-subscriptions';
import {
decodeOffsetCursor,
encodeCursor,
} from 'src/core/base/pagination.util';
import { DocumentInfoArgs, TicketFilterArgs } from './ticket-arg.types';
import { TicketLifecycleService } from './ticket-lifecycle.service';
import {
TicketSystemEventTypes,
TicketSystemValidatedEvent,
} from './ticket-system.events';
import {
PaginatedTicketObjectType,
TicketStateKeyFiguresObjectType,
TicketStateMetaObjectType,
} from './ticket.object-type';
import { TicketRepository } from './ticket.repository';
@Injectable()
export class TicketService {
public readonly pubSub = new PubSub();
@OnEvent(TicketSystemEventTypes.Validated, { async: true })
notifyOnTicketsValidated(event: TicketSystemValidatedEvent): void {
this.pubSub.publish('ticketsUpdated', {
ticketsUpdated: { count: event.count },
});
}
constructor(
private readonly repository: TicketRepository,
private readonly lifecycle: TicketLifecycleService,
private readonly eventEmitter: EventEmitter2,
) {}
async createTickets(interval: Interval): Promise<void> {
await this.lifecycle.createTickets(interval);
this.eventEmitter.emit(
TicketSystemEventTypes.Validated,
new TicketSystemValidatedEvent(0),
);
}
async updateDocumentInfo(ticketId: string, documentInfo: DocumentInfoArgs) {
return this.lifecycle.validateDocumentInfoUpdate(ticketId, documentInfo);
}
findById(id: string): Promise<Ticket> {
return this.repository.findById(id);
}
findAll(): Promise<Ticket[]> {
return this.repository.findAll() as Promise<Ticket[]>;
}
searchTickets(query: string): Promise<Ticket[]> {
return this.repository.search(query);
}
async paginateTicketsByState(
state: TicketValidationState,
filter: TicketFilterArgs,
take?: number,
cursor?: string,
): Promise<PaginatedTicketObjectType> {
const skip = cursor ? decodeOffsetCursor(cursor) : 0;
const { tickets, total } = await this.repository.findByState(
state,
filter,
take,
skip,
);
const prevPage = skip - take < 0 ? 0 : skip - take;
const nextPage = skip + take < total ? skip + take : skip;
return {
nodes: tickets,
prevCursor: encodeCursor(prevPage),
endCursor: encodeCursor(nextPage),
hasNextPage: nextPage !== skip,
totalCount: total,
};
}
async getTicketStateMeta(
ticketState: TicketValidationState,
): Promise<TicketStateMetaObjectType> {
return this.repository.calculateTicketStateMeta(ticketState);
}
getTicketStateKeyFigures(
ticketState: TicketValidationState,
): Promise<TicketStateKeyFiguresObjectType> {
return this.repository.calculateTicketStateKeyFigures(ticketState);
}
findToursByTicketId(ticketId: string): Promise<Tour[]> {
return this.repository.findToursByTicketId(ticketId);
}
findStatesByTicketId(ticketId: string): Promise<TicketValidationState[]> {
return this.repository
.findStatesByTicketId(ticketId)
.then((states) => states.map(({ state }) => state));
}
}