feat(ticket-list): added a route to fetch all tickets, filtered in a precis order
This commit is contained in:
parent
d14924783d
commit
f43d3ade19
|
|
@ -1,13 +1,17 @@
|
||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
import { CreateTicketService } from "src/customer-support/tickets/services/create-ticket.service";
|
||||||
|
import { GetTicketListService } from "src/customer-support/tickets/services/get-ticket-list.service";
|
||||||
|
import { UpdateTicketService } from "src/customer-support/tickets/services/update-ticket.service";
|
||||||
import { TicketController } from "src/customer-support/tickets/ticket.controller";
|
import { TicketController } from "src/customer-support/tickets/ticket.controller";
|
||||||
import { TicketService } from "src/customer-support/tickets/ticket.service";
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [
|
controllers: [
|
||||||
TicketController
|
TicketController
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
TicketService
|
GetTicketListService,
|
||||||
|
CreateTicketService,
|
||||||
|
UpdateTicketService,
|
||||||
],
|
],
|
||||||
|
|
||||||
}) export class CustomerSupportModule { }
|
}) export class CustomerSupportModule { }
|
||||||
|
|
@ -1 +1 @@
|
||||||
GET http://localhost:3000/tickets/OPEN?sortOrder=last_update&sortTypes=DESC&offset=0&limit=10&email=gilles@targointernet.com
|
GET http://localhost:3000/tickets/OPEN?sortOrder=last_update&sortTypes=DESC&offset=0&limit=30&email=gilles@targointernet.com
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { PrismaMariaDbService } from "prisma/mariadb/prisma-mariadb.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CreateTicketService {
|
||||||
|
constructor(private readonly prisma: PrismaMariaDbService) { }
|
||||||
|
|
||||||
|
createTicket = async () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/customer-support/tickets/services/get-ticket-list.service.ts
Normal file
132
src/customer-support/tickets/services/get-ticket-list.service.ts
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
import { PrismaMariaDbService } from "prisma/mariadb/prisma-mariadb.service";
|
||||||
|
import { TicketList } from "src/customer-support/tickets/dtos/ticket-list.dto";
|
||||||
|
import { sortOrders, sortTypes } from "src/customer-support/tickets/dtos/ticket.dto";
|
||||||
|
import { Prisma } from "prisma/mariadb/generated/prisma/client/mariadb/client";
|
||||||
|
|
||||||
|
export const TIMESTAMP_MINIMUM = 1672531200; // 1er janvier 2023
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetTicketListService {
|
||||||
|
constructor(private readonly prisma: PrismaMariaDbService) { }
|
||||||
|
|
||||||
|
getListOfAllTicketByFilters = async (
|
||||||
|
status: string[],
|
||||||
|
offset: number = 0,
|
||||||
|
limit: number = 25,
|
||||||
|
sortOrder: string = 'last_update',
|
||||||
|
sortType: 'DESC' | 'ASC' = 'DESC',
|
||||||
|
email?: string
|
||||||
|
): Promise<Result<TicketList[], string>> => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const staff = await this.prisma.staff.findFirst({
|
||||||
|
where: { email },
|
||||||
|
});
|
||||||
|
if (!staff) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
|
||||||
|
if (!sortOrders.includes(sortOrder) || !sortTypes.includes(sortType)) return { success: false, error: 'INVALID_FILTER' }
|
||||||
|
|
||||||
|
const statusList = Prisma.join(status);
|
||||||
|
|
||||||
|
const rawTicketList = await this.prisma.$queryRaw<TicketList[]>(
|
||||||
|
Prisma.sql`
|
||||||
|
SELECT
|
||||||
|
t.id AS id,
|
||||||
|
t.status AS status,
|
||||||
|
CONCAT(s.first_name,' ',s.last_name) AS assignTo,
|
||||||
|
a.address1 AS deliveryAddress,
|
||||||
|
t.subject AS subject,
|
||||||
|
d.name AS department,
|
||||||
|
t.parent AS parentTicketId,
|
||||||
|
|
||||||
|
CASE
|
||||||
|
WHEN t.due_date > 1672531200
|
||||||
|
THEN FROM_UNIXTIME(t.due_date, '%d/%m/%y')
|
||||||
|
ELSE NULL
|
||||||
|
END AS dueDate,
|
||||||
|
|
||||||
|
FROM_UNIXTIME(t.last_update, '%d/%m/%y') AS lastUpdate,
|
||||||
|
|
||||||
|
CASE
|
||||||
|
WHEN CAST(t.date_closed AS UNSIGNED) > 1672531200
|
||||||
|
THEN FROM_UNIXTIME(CAST(t.date_closed AS UNSIGNED), '%d/%m/%y')
|
||||||
|
ELSE NULL
|
||||||
|
END AS completedAt
|
||||||
|
|
||||||
|
FROM staff s
|
||||||
|
LEFT JOIN ticket t ON t.assign_to = s.id
|
||||||
|
LEFT JOIN account a ON t.account_id = a.id
|
||||||
|
LEFT JOIN ticket_dept d ON t.dept_id = d.id
|
||||||
|
WHERE s.id = ${staff.id}
|
||||||
|
AND t.status IN (${statusList})
|
||||||
|
ORDER BY ${Prisma.raw(sortOrder)} ${Prisma.raw(sortType)}
|
||||||
|
LIMIT ${limit} OFFSET ${offset}
|
||||||
|
`);
|
||||||
|
|
||||||
|
return { success: true, data: rawTicketList }
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: 'TICKET_LIST_NOT_FOUND, ' + error };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getListOfTickets = async (
|
||||||
|
email: string,
|
||||||
|
offset: number = 0,
|
||||||
|
limit: number = 25,
|
||||||
|
): Promise<Result<TicketList[], string>> => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const staff = await this.prisma.staff.findFirst({
|
||||||
|
where: { email },
|
||||||
|
});
|
||||||
|
if (!staff) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
|
||||||
|
|
||||||
|
const rawTicketList = await this.prisma.$queryRaw<TicketList[]>(
|
||||||
|
Prisma.sql`
|
||||||
|
SELECT
|
||||||
|
t.id AS id,
|
||||||
|
t.status AS status,
|
||||||
|
CONCAT(s.first_name,' ',s.last_name) AS assignTo,
|
||||||
|
a.address1 AS deliveryAddress,
|
||||||
|
t.subject AS subject,
|
||||||
|
d.name AS department,
|
||||||
|
t.parent AS parentTicketId,
|
||||||
|
|
||||||
|
CASE
|
||||||
|
WHEN t.due_date > 1672531200
|
||||||
|
THEN FROM_UNIXTIME(t.due_date, '%d/%m/%y')
|
||||||
|
ELSE NULL
|
||||||
|
END AS dueDate,
|
||||||
|
|
||||||
|
FROM_UNIXTIME(t.last_update, '%d/%m/%y') AS lastUpdate,
|
||||||
|
|
||||||
|
CASE
|
||||||
|
WHEN CAST(t.date_closed AS UNSIGNED) > 1672531200
|
||||||
|
THEN FROM_UNIXTIME(CAST(t.date_closed AS UNSIGNED), '%d/%m/%y')
|
||||||
|
ELSE NULL
|
||||||
|
END AS completedAt
|
||||||
|
|
||||||
|
FROM staff s
|
||||||
|
LEFT JOIN ticket t ON t.assign_to = s.id
|
||||||
|
LEFT JOIN account a ON t.account_id = a.id
|
||||||
|
LEFT JOIN ticket_dept d ON t.dept_id = d.id
|
||||||
|
WHERE s.id = ${staff.id}
|
||||||
|
ORDER BY
|
||||||
|
CASE
|
||||||
|
WHEN t.status = 'open' AND t.assign_to = 0 THEN 0
|
||||||
|
WHEN t.status = 'open' AND t.assign_to = s.id THEN 1
|
||||||
|
WHEN t.status = 'pending' AND t.assign_to = s.id THEN 2
|
||||||
|
WHEN t.status = 'open' AND t.assign_to != s.id THEN 3
|
||||||
|
WHEN t.status = 'pending' AND t.assign_to != s.id THEN 4
|
||||||
|
ELSE 5
|
||||||
|
END
|
||||||
|
LIMIT ${limit} OFFSET ${offset};
|
||||||
|
`);
|
||||||
|
|
||||||
|
return { success: true, data: rawTicketList }
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: 'TICKET_LIST_NOT_FOUND, ' + error };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { PrismaMariaDbService } from "prisma/mariadb/prisma-mariadb.service";
|
||||||
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UpdateTicketService {
|
||||||
|
constructor(private readonly prisma: PrismaMariaDbService) { }
|
||||||
|
|
||||||
|
updateTicketById = async (
|
||||||
|
ticketId: number
|
||||||
|
): Promise<Result<boolean, string>> => {
|
||||||
|
try {
|
||||||
|
await this.prisma.ticket.update({
|
||||||
|
where: { id: ticketId },
|
||||||
|
data: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
return { success: true, data: true }
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
return { success: false, error: 'INVALID_TICKET_ID' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,12 +2,12 @@ import { Controller, Get, Param, ParseIntPipe, Query } from "@nestjs/common";
|
||||||
import { Access } from "src/common/decorators/module-access.decorators";
|
import { Access } from "src/common/decorators/module-access.decorators";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
import { TicketList } from "src/customer-support/tickets/dtos/ticket-list.dto";
|
import { TicketList } from "src/customer-support/tickets/dtos/ticket-list.dto";
|
||||||
import { TicketService } from "src/customer-support/tickets/ticket.service";
|
import { GetTicketListService } from "src/customer-support/tickets/services/get-ticket-list.service";
|
||||||
|
|
||||||
@Controller('tickets')
|
@Controller('tickets')
|
||||||
export class TicketController {
|
export class TicketController {
|
||||||
|
|
||||||
constructor(private readonly getService: TicketService) { }
|
constructor(private readonly getService: GetTicketListService) { }
|
||||||
|
|
||||||
@Get(':status')
|
@Get(':status')
|
||||||
async findTicketByFilters(
|
async findTicketByFilters(
|
||||||
|
|
@ -31,4 +31,17 @@ export class TicketController {
|
||||||
queryEmail,
|
queryEmail,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('list')
|
||||||
|
async findTicketList(
|
||||||
|
@Access('email') email:string,
|
||||||
|
@Query('offset', ParseIntPipe) offset: number,
|
||||||
|
@Query('limit', ParseIntPipe) limit: number,
|
||||||
|
) {
|
||||||
|
return await this.getService.getListOfTickets(
|
||||||
|
email,
|
||||||
|
offset,
|
||||||
|
limit
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { Module } from "@nestjs/common";
|
import { Module } from "@nestjs/common";
|
||||||
|
import { GetTicketListService } from "src/customer-support/tickets/services/get-ticket-list.service";
|
||||||
import { TicketController } from "src/customer-support/tickets/ticket.controller";
|
import { TicketController } from "src/customer-support/tickets/ticket.controller";
|
||||||
import { TicketService } from "src/customer-support/tickets/ticket.service";
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TicketService
|
GetTicketListService
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
TicketController
|
TicketController
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import { Injectable } from "@nestjs/common";
|
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
|
||||||
import { PrismaMariaDbService } from "prisma/mariadb/prisma-mariadb.service";
|
|
||||||
import { TicketList } from "src/customer-support/tickets/dtos/ticket-list.dto";
|
|
||||||
import { sortOrders, sortTypes } from "src/customer-support/tickets/dtos/ticket.dto";
|
|
||||||
import { Prisma } from "prisma/mariadb/generated/prisma/client/mariadb/client";
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TicketService {
|
|
||||||
constructor(private readonly prisma: PrismaMariaDbService) { }
|
|
||||||
|
|
||||||
getListOfAllTicketByFilters = async (
|
|
||||||
status: string[],
|
|
||||||
offset: number = 0,
|
|
||||||
limit: number = 25,
|
|
||||||
sortOrder: string = 'last_update',
|
|
||||||
sortType: 'DESC' | 'ASC' = 'DESC',
|
|
||||||
email?: string
|
|
||||||
): Promise<Result<TicketList[], string>> => {
|
|
||||||
|
|
||||||
try {
|
|
||||||
const staff = await this.prisma.staff.findFirst({
|
|
||||||
where: { email },
|
|
||||||
});
|
|
||||||
if (!staff) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
|
|
||||||
if (!sortOrders.includes(sortOrder) || !sortTypes.includes(sortType)) return { success: false, error: 'INVALID_FILTER' }
|
|
||||||
|
|
||||||
const statusList = Prisma.join(status);
|
|
||||||
|
|
||||||
const rawticketList = await this.prisma.$queryRaw<TicketList[]>(
|
|
||||||
Prisma.sql`
|
|
||||||
SELECT
|
|
||||||
t.id AS id,
|
|
||||||
t.status AS status,
|
|
||||||
CONCAT(s.first_name,' ',s.last_name) AS assignTo,
|
|
||||||
a.address1 AS deliveryAddress,
|
|
||||||
t.subject AS subject,
|
|
||||||
d.name AS department,
|
|
||||||
t.parent AS parentTicketId,
|
|
||||||
DATE_FORMAT(FROM_UNIXTIME(t.due_date / 1000), '%d/%m/%y') AS dueDate,
|
|
||||||
DATE_FORMAT(FROM_UNIXTIME(t.last_update / 1000), '%d/%m/%y') AS updatedAt,
|
|
||||||
CASE
|
|
||||||
WHEN t.date_closed IS NOT NULL
|
|
||||||
THEN DATE_FORMAT(FROM_UNIXTIME(t.date_closed / 1000), '%d/%m/%y')
|
|
||||||
ELSE NULL
|
|
||||||
END AS completedAt
|
|
||||||
FROM staff s
|
|
||||||
LEFT JOIN ticket t ON t.assign_to = s.id
|
|
||||||
LEFT JOIN account a ON t.account_id = a.id
|
|
||||||
LEFT JOIN ticket_dept d ON t.dept_id = d.id
|
|
||||||
WHERE s.email = ${email}
|
|
||||||
AND t.status IN (${statusList})
|
|
||||||
ORDER BY ${Prisma.raw(sortOrder)} ${Prisma.raw(sortType)}
|
|
||||||
LIMIT ${limit} OFFSET ${offset};
|
|
||||||
`);
|
|
||||||
|
|
||||||
return { success: true, data: rawticketList }
|
|
||||||
} catch (error) {
|
|
||||||
return { success: false, error: 'TICKET_LIST_NOT_FOUND, ' + error };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user