updated tickets
This commit is contained in:
+312
-4
@@ -24,6 +24,7 @@ export function buildOpenApiDocument() {
|
||||
{ name: 'Provoz', description: 'Health a zakladni informace' },
|
||||
{ name: 'Autentizace', description: 'Prihlaseni do portalu' },
|
||||
{ name: 'Dashboard', description: 'Data klientskeho portalu' },
|
||||
{ name: 'Tickety', description: 'Pozadavky, jejich resitele a log prubehu' },
|
||||
{ name: 'Automatizace', description: 'Sprava automatizaci a stromu akci' },
|
||||
{ name: 'Simulace', description: 'Vyvolani provoznich udalosti pro nahled' },
|
||||
{ name: 'Webhook', description: 'Verejny prijem dat do automatizace' },
|
||||
@@ -71,19 +72,130 @@ export function buildOpenApiDocument() {
|
||||
user: { $ref: '#/components/schemas/User' },
|
||||
},
|
||||
},
|
||||
Person: {
|
||||
type: 'object',
|
||||
description: 'Resitel ticketu. Nemusi mit ucet v portalu, spojka je e-mail.',
|
||||
properties: {
|
||||
id: { type: 'string', example: 'ppl_vomacka' },
|
||||
name: { type: 'string', example: 'Karel Vomacka' },
|
||||
email: { type: 'string', format: 'email' },
|
||||
role: { type: 'string', example: 'Servicedesk' },
|
||||
capacity: {
|
||||
type: 'integer',
|
||||
description: 'Kolik nevyrizenych ticketu je pro nej jeste zdrava zatez.',
|
||||
},
|
||||
},
|
||||
},
|
||||
TicketCustomer: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
description: 'ID firmy v CRM. null = zakaznika se nepodarilo dohledat.',
|
||||
example: 'crm_1042',
|
||||
},
|
||||
company: { type: 'string', example: 'Firma s.r.o.' },
|
||||
contact: { type: 'string', example: 'Petra Klientova' },
|
||||
reply: {
|
||||
type: 'string',
|
||||
description: 'Adresa nebo cislo, odkud pozadavek prisel a kam se odpovida.',
|
||||
},
|
||||
},
|
||||
},
|
||||
Ticket: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', example: 'TK-4821' },
|
||||
subject: { type: 'string' },
|
||||
requester: { type: 'string' },
|
||||
channel: {
|
||||
type: 'string',
|
||||
enum: ['whatsapp', 'email', 'voice', 'form', 'portal'],
|
||||
description: 'Odkud pozadavek prisel.',
|
||||
},
|
||||
customer: { $ref: '#/components/schemas/TicketCustomer' },
|
||||
status: { type: 'string', enum: ['new', 'open', 'waiting', 'resolved'] },
|
||||
priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'] },
|
||||
assignee: { type: 'string', nullable: true },
|
||||
assignee: {
|
||||
type: 'object',
|
||||
nullable: true,
|
||||
description: 'Kdo ma ticket u sebe. null = ceka ve fronte.',
|
||||
properties: {
|
||||
id: { type: 'string', example: 'ppl_vomacka' },
|
||||
name: { type: 'string', example: 'Karel Vomacka' },
|
||||
},
|
||||
},
|
||||
automationId: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
description: 'Automatizace, ktera ticket zalozila. null = zalozeno rucne.',
|
||||
},
|
||||
createdAt: { type: 'string', format: 'date-time' },
|
||||
updatedAt: { type: 'string', format: 'date-time' },
|
||||
},
|
||||
},
|
||||
TicketTraceEntry: {
|
||||
type: 'object',
|
||||
description:
|
||||
'Jeden radek logu ticketu. Strom se sklada pres parentId - vetev podminky ' +
|
||||
'visi na zaznamu te podminky.',
|
||||
properties: {
|
||||
id: { type: 'string', example: 'tr_12' },
|
||||
parentId: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
description: 'null = zaznam v hlavni sekvenci.',
|
||||
},
|
||||
kind: { type: 'string', enum: ['trigger', 'action', 'condition', 'note'] },
|
||||
connectorId: { type: 'string', nullable: true, example: 'raynet' },
|
||||
operationId: { type: 'string', nullable: true, example: 'upsert-contact' },
|
||||
label: { type: 'string' },
|
||||
status: { type: 'string', enum: ['ok', 'error', 'skipped', 'info'] },
|
||||
response: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
description: 'Co sluzba vratila. Kvuli tomuhle log existuje.',
|
||||
},
|
||||
durationMs: { type: 'integer', nullable: true },
|
||||
at: { type: 'string', format: 'date-time' },
|
||||
},
|
||||
},
|
||||
TicketDetail: {
|
||||
allOf: [
|
||||
{ $ref: '#/components/schemas/Ticket' },
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
trace: {
|
||||
type: 'array',
|
||||
items: { $ref: '#/components/schemas/TicketTraceEntry' },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
Workload: {
|
||||
type: 'object',
|
||||
description: 'Prehled nad firmou - kdo ma kolik ticketu u sebe.',
|
||||
properties: {
|
||||
rows: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
person: { $ref: '#/components/schemas/Person' },
|
||||
open: { type: 'integer', description: 'Nevyresene tickety.' },
|
||||
total: { type: 'integer' },
|
||||
critical: { type: 'integer' },
|
||||
oldestOpenAt: { type: 'string', format: 'date-time', nullable: true },
|
||||
overloaded: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
},
|
||||
unassigned: { type: 'integer', description: 'Nevyresene tickety bez resitele.' },
|
||||
openTotal: { type: 'integer' },
|
||||
},
|
||||
},
|
||||
Incident: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -288,11 +400,58 @@ export function buildOpenApiDocument() {
|
||||
responses: { '200': { description: 'Souhrnne metriky a casova rada' } },
|
||||
},
|
||||
},
|
||||
'/api/dashboard/people': {
|
||||
get: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Seznam resitelu',
|
||||
description:
|
||||
'Lide, na ktere jde ticket priradit. `meId` je resitel odpovidajici ' +
|
||||
'prihlasenemu uzivateli, nebo null, pokud zadny neni.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Resitele',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
items: { type: 'array', items: { $ref: '#/components/schemas/Person' } },
|
||||
meId: { type: 'string', nullable: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets': {
|
||||
get: {
|
||||
tags: ['Dashboard'],
|
||||
tags: ['Tickety'],
|
||||
summary: 'Seznam ticketu',
|
||||
description: 'Neznama hodnota filtru se ignoruje a zaloguje, seznam se nezuzi.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
parameters: [
|
||||
{
|
||||
name: 'assignee',
|
||||
in: 'query',
|
||||
schema: { type: 'string' },
|
||||
description:
|
||||
'ID resitele, `me` pro prihlaseneho uzivatele, nebo `unassigned` pro frontu.',
|
||||
example: 'me',
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
in: 'query',
|
||||
schema: { type: 'string', enum: ['new', 'open', 'waiting', 'resolved'] },
|
||||
},
|
||||
{
|
||||
name: 'channel',
|
||||
in: 'query',
|
||||
schema: { type: 'string', enum: ['whatsapp', 'email', 'voice', 'form', 'portal'] },
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Tickety',
|
||||
@@ -302,6 +461,7 @@ export function buildOpenApiDocument() {
|
||||
type: 'object',
|
||||
properties: {
|
||||
items: { type: 'array', items: { $ref: '#/components/schemas/Ticket' } },
|
||||
meId: { type: 'string', nullable: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -310,6 +470,144 @@ export function buildOpenApiDocument() {
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets/workload': {
|
||||
get: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Kdo co ma u sebe',
|
||||
description: 'Prehled zateze pres cely tym vcetne poctu ticketu ve fronte.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Vytizeni resitelu',
|
||||
content: {
|
||||
'application/json': { schema: { $ref: '#/components/schemas/Workload' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets/{id}': {
|
||||
get: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Detail ticketu vcetne logu',
|
||||
description: 'Log obsahuje i to, co ktera volana sluzba vratila.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
parameters: [
|
||||
{
|
||||
name: 'id',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: { type: 'string' },
|
||||
example: 'TK-4821',
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Detail',
|
||||
content: {
|
||||
'application/json': { schema: { $ref: '#/components/schemas/TicketDetail' } },
|
||||
},
|
||||
},
|
||||
'404': { description: 'Neexistuje' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets/{id}/assign': {
|
||||
post: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Priradit resitele',
|
||||
description: 'Poslete null pro vraceni ticketu do fronty.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['assigneeId'],
|
||||
properties: {
|
||||
assigneeId: { type: 'string', nullable: true, example: 'ppl_vomacka' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Prirazeno',
|
||||
content: {
|
||||
'application/json': { schema: { $ref: '#/components/schemas/Ticket' } },
|
||||
},
|
||||
},
|
||||
'400': { description: 'Chybi assigneeId' },
|
||||
'404': { description: 'Ticket nebo resitel neexistuje' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets/{id}/status': {
|
||||
post: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Zmenit stav ticketu',
|
||||
security: [{ bearerAuth: [] }],
|
||||
parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['status'],
|
||||
properties: {
|
||||
status: { type: 'string', enum: ['new', 'open', 'waiting', 'resolved'] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Zmeneno',
|
||||
content: {
|
||||
'application/json': { schema: { $ref: '#/components/schemas/Ticket' } },
|
||||
},
|
||||
},
|
||||
'400': { description: 'Neplatny stav' },
|
||||
'404': { description: 'Neexistuje' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/tickets/{id}/comment': {
|
||||
post: {
|
||||
tags: ['Tickety'],
|
||||
summary: 'Pridat komentar',
|
||||
description: 'Komentar je dalsi radek logu, aby bylo vse na jedne casove ose.',
|
||||
security: [{ bearerAuth: [] }],
|
||||
parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['text'],
|
||||
properties: { text: { type: 'string', minLength: 2 } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'Zapsano',
|
||||
content: {
|
||||
'application/json': { schema: { $ref: '#/components/schemas/Ticket' } },
|
||||
},
|
||||
},
|
||||
'400': { description: 'Prazdny komentar' },
|
||||
'404': { description: 'Neexistuje' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/dashboard/incidents': {
|
||||
get: {
|
||||
tags: ['Dashboard'],
|
||||
@@ -502,7 +800,17 @@ export function buildOpenApiDocument() {
|
||||
],
|
||||
},
|
||||
subject: { type: 'string' },
|
||||
requester: { type: 'string' },
|
||||
channel: {
|
||||
type: 'string',
|
||||
enum: ['whatsapp', 'email', 'voice', 'form', 'portal'],
|
||||
description: 'Odkud pozadavek prisel. Podle toho se poskladá i log ticketu.',
|
||||
},
|
||||
contact: { type: 'string' },
|
||||
knownCustomer: {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'false = CRM firmu nedohleda, ticket zustane bez zakaznika i bez resitele.',
|
||||
},
|
||||
priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'] },
|
||||
ticketId: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
|
||||
Reference in New Issue
Block a user