Vyrizeno je vyslovny priznak, ne hadani ze stavu

`Ticket.closed` se nastavuje vyslovne. Predchozi verze ho odvozovala ze jmena
stavu (completed, vyreseno, ...), coz nikdo nechtel a hlavne to uhodne spatne
pokazde, kdyz si nekdo pojmenuje stavy po svem. `TicketType.closedStatuses`
zruseno, byla to tatáz obchazka o uroven vys.

Kroky `ticket/upsert` a `ticket/set-status` maji vstup Vyrizeny s trema stavy:
ano, ne, prazdne. Prazdne znamena nemenit - jinak by kazda zmena textu stavu
mimochodem otevrela vyrizeny ticket. `POST /tickets/:id/status` prijima
`closed` jako nepovinny bool a podminka ve strome se na nej muze zeptat.

Overeno 8 kontrolami: ticket se stavem completed neni automaticky vyrizeny,
dokud to nekdo nerekne. Automatizace s podminkou status = completed zabere na
ticketu, ktery do toho stavu prejde, ale na uz existujici tickety nesahne -
spousti ji udalost, ne stav.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-14 07:38:20 +02:00
co-authored by Claude Opus 5
parent 202d525905
commit fbe5b8ff6f
7 changed files with 118 additions and 84 deletions
+7 -8
View File
@@ -48,11 +48,10 @@ import { listNotifications, markRead, unreadCount } from '../data/notifications.
import { queueStats, recentRuns } from '../runtime/queue.js';
import { recordAudit } from '../data/audit.js';
import { findTenant, generateIntakeToken, refreshTenants, tenantStore } from '../data/tenants.js';
import { findTicketType, listTicketTypes } from '../data/ticketTypes.js';
import { listTicketTypes } from '../data/ticketTypes.js';
import {
addComment,
assignTicket,
findTicket,
getAgentStats,
getTicket,
getWorkload,
@@ -608,6 +607,11 @@ const statusSchema = z.object({
* nesmysl. Omezena je jen delka, aby se do pole nedal cely dokument.
*/
status: z.string().trim().min(1).max(60),
/**
* Je vyrizeny? Kdyz se neposle, priznak zustava - zmena textu stavu sama
* o sobe neznamena, ze je hotovo.
*/
closed: z.boolean().optional(),
});
dashboardRouter.post('/tickets/:id/status', (req, res) => {
@@ -616,16 +620,11 @@ dashboardRouter.post('/tickets/:id/status', (req, res) => {
return res.status(400).json({ error: 'validation_error', message: 'Neplatný stav ticketu.' });
}
// Typ rika, ktere z jeho stavu znamenaji hotovo. Bez nej se to pozna
// podle bezneho pojmenovani (vyreseno, completed).
const current = findTicket(req.params.id, writableTenants(req));
const type = current?.typeId ? findTicketType(current.typeId) : undefined;
const ticket = updateTicketStatus(
req.params.id,
parsed.data.status,
writableTenants(req),
type?.closedStatuses,
parsed.data.closed,
);
if (!ticket) {
return res.status(404).json({ error: 'not_found', message: 'Ticket neexistuje.' });