---
title: "Stavy a prechody — Tickets for Laravel | Roundly"
description: "Sedem stavov, päť kategórií a deväť prechodov — plus pomenované skratky, automatizácie, automatické uzavretie, zámok konverzácie a vlastné cykly."
url: https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel/stavy-a-prechody
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Tickets for Laravel](https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel.md)

# Stavy a prechody

Stavy tiketov bežia na lifecycle-for-laravel: definícia v kóde, prechody s pravidlami, pečiatky, TTL, história a idempotencia. Tickets nikdy sám nezapisuje stĺpec status a jeho vlastná logika číta len päť kategórií stavov, nikdy konkrétny stav — preto sa dá životný cyklus vymeniť.

## Stavy

| Stav | Kategória | Poznámky |
| --- | --- | --- |
| `new` | Open | počiatočný |
| `open` | Open | — |
| `in_progress` | Active | — |
| `pending` | Waiting | čaká na žiadateľa |
| `on_hold` | Waiting | čaká na tretiu stranu |
| `resolved` | Resolved | zaznamená resolved\_at; po tickets.auto\_close.after sa automaticky uzavrie |
| `closed` | Closed | koncový; zaznamená closed\_at |

## Prechody

| Prechod (konštanta) | Z | Do | Pravidlá |
| --- | --- | --- | --- |
| `open (OPEN)` | `new` | `open` | povolené aj pre systém |
| `start (START)` | `new, open, pending, on_hold` | `in_progress` | — |
| `wait (WAIT)` | `new, open, in_progress` | `pending` | — |
| `hold (HOLD)` | `new, open, in_progress` | `on_hold` | povinný dôvod |
| `resume (RESUME)` | `pending, on_hold` | `open` | povolené aj pre systém |
| `resolve (RESOLVE)` | `new, open, in_progress, pending, on_hold` | `resolved` | payload resolution (voliteľný reťazec, ≤ 5000) |
| `reopen (REOPEN)` | `resolved` | `open` | povolené aj pre systém |
| `close (CLOSE)` | `resolved` | `closed` | povolené aj pre systém |
| `dismiss (DISMISS)` | každý stav okrem closed | `closed` | povinný dôvod; povolené aj pre systém |

dismiss pokrýva aj resolved, aby sa vyriešený tiket dal stále zlúčiť alebo zahodiť ako spam. S close zdieľa resolved → closed, preto lifecycle:validate hlási jedno upozornenie ambiguous\_target, ktoré tickets:doctor vyhodnotí ako ok. Prechody vždy spúšťajte podľa názvu: na vyriešenom tikete nikdy nevolajte $ticket->transitionTo(TicketStatus::Closed) — pri dvoch možných prechodoch vyhodí AmbiguousTransitionException. Použite close() (alebo transition('close')), prípadne dismiss($reason).

## Kategórie stavov

| Kategória | Nevyriešené | Význam |
| --- | --- | --- |
| Open | áno | nová, ešte netriedená práca |
| Active | áno | niekto na ňom pracuje |
| Waiting | áno | čaká na žiadateľa alebo tretiu stranu — prekročenie termínu sa stále ráta |
| Resolved | nie | — |
| Closed | nie | konverzácia je zamknutá |

## Spúšťanie prechodov

```php
Tickets::for($ticket)->by($agent)->transition('resolve', reason: null, payload: ['resolution' => 'Roller replaced.']);

// Named conveniences — the shipped lifecycle's transitions, each returning the handle
Tickets::for($ticket)->by($agent)->start()->wait();
Tickets::for($ticket)->by($agent)->hold('Waiting for the vendor');
Tickets::for($ticket)->by($agent)->resolve('Roller replaced.');
Tickets::for($ticket)->by($requester)->reopen();
Tickets::for($ticket)->by($agent)->dismiss('Spam');

Tickets::for($ticket)->can('close');           // bool, for this actor, now
Tickets::for($ticket)->allowedTransitions();   // ['wait', 'hold', 'resolve', 'dismiss', …]
Tickets::for($ticket)->status();               // TicketStatus::InProgress
```

- transition() vracia TransitionResult z lifecycle; pomenované skratky vracajú handle.
- Zamietnutie vyhodí TransitionDeniedException z lifecycle s kódmi zamietnutia — API odpovie 422 ticket\_transition\_denied, alebo 429 s Retry-After, keď zamietnutie uvádza, kedy to skúsiť znova.
- Skratka, ktorú nakonfigurovaný životný cyklus nemá, vyhodí UnknownTicketTransitionException — použite transition() s názvami vášho cyklu. tickets:doctor vypíše, ktoré skratky podporuje.
- Prechody soft-deleted tiketu sa odmietnu (SubjectTrashedException).
- asSystem() beží bez aktéra; dodaný cyklus povolí systému len open, resume, reopen, close a dismiss, takže import či skript odovzdá pre čokoľvek iné aktéra.
- PHP API uplatní to, čo lifecycle aktérovi povolí; kto sa smie pýtať, rozhodujete vy. Policy API povolí agentom akýkoľvek prechod a žiadateľom len tickets.authorization.requester\_transitions (predvolene close a reopen; pri participants\_can\_transition aj sledujúcemu).

## Automatizácie

Prechody, ktoré spúšťa balík, bežia ako systém (žiadateľa teda nikdy neposudzujú pravidlá aktérov životného cyklu) a v zázname aktivity sa pripíšu aktérovi, ktorý ich vyvolal. Nakonfigurovaný cyklus priradí každému háčiku jeden zo svojich prechodov, alebo null na vypnutie:

| Automatizácia | Kedy | Dodaný prechod | Musí opustiť | Musí skončiť v |
| --- | --- | --- | --- | --- |
| `Assigned` | tiket v počiatočnom stave dostane riešiteľa (aj pri založení) | `open` | počiatočný stav | Open, Active |
| `RequesterReplied` | žiadateľ alebo účastník odpovie počas stavu Waiting | `resume` | každý stav Waiting | Open, Active |
| `RequesterReopened` | žiadateľ alebo účastník odpovie počas stavu Resolved (tickets.comments.reply\_reopens) | `reopen` | každý stav Resolved | Open, Active, Waiting |
| `AutoClose` | vyprší TTL vyriešeného tiketu (sweep z lifecycle) | `close` | každý stav Resolved | Closed |
| `Merged` | tiket sa zlúči do iného | `dismiss` | každý stav Open, Active, Waiting, Resolved | Closed |

Každý priradený prechod musí povoľovať systémový kontext. Explicitné transition: pri odpovedi nahradí automatizáciu odpovede. Odpoveď, ktorú zadrží moderácia hostiteľa, nespustí ani jedno — žiadnu automatizáciu ani explicitný prechod.

## Automatické uzavretie

- Dodaný stav resolved má TTL tickets.auto\_close.after (predvolene P7D, alebo off pre nikdy), ktoré vyprší cez close. Nezmyselná hodnota vyhodí InvalidTicketsConfigurationException.
- TTL sa číta, keď tiket vstúpi do stavu Resolved, takže zmena konfigurácie ovplyvní len neskoršie vyriešenia.
- Vypršanie uplatní lifecycle:sweep — naplánujte ho každú minútu. tickets:sweep nikdy nič neuzatvára.
- Znovuotvorenie (alebo zlúčenie, ktoré tiket zahodí) čakajúce automatické uzavretie zruší.

## Zámok konverzácie

Listener na LifecycleTransitioning z lifecycle (v transakcii prechodu) zamkne vlákno comments-for-laravel tiketu, keď je kategória cieľového stavu Closed, a odomkne ho, keď tiket stav Closed opustí. Funguje s akýmkoľvek životným cyklom bez kódu na vašej strane; rollbacky a adopcie zámok zosynchronizujú po potvrdení. Pri tickets.guests.revoke\_on\_close vstup do Closed zneplatní aj všetky odkazy pre hostí.

## Udalosti stavov

Každý prechod zapíše záznam aktivity status\_changed atomicky so stavom a — po potvrdení — spustí TicketStatusChanged a udalosti vstupu do kategórie: TicketResolved (vstup do Resolved), TicketClosed (vstup do Closed) a TicketReopened (odchod z Resolved alebo Closed do Open, Active či Waiting). Počiatočný riadok histórie žiadnu nespustí; pokrýva ho aktivita created.

## Výmena životného cyklu

```php
// config/tickets.php
'lifecycle' => App\Tickets\SupportLifecycle::class,
```

Najmenšia zmena je zdediť dodanú triedu (nie je final) a upraviť define(). Úplne vlastná definícia musí dediť od LifecycleDefinition z lifecycle a implementovať Contracts\\TicketLifecycle (automation(Automation $hook): ?string), používať enum stavov s Contracts\\TicketState (category(): StatusCategory), byť životným cyklom status modelu tiketu a každú automatizáciu, ktorá nie je null, priradiť existujúcemu prechodu, ktorý povoľuje systémový kontext a zodpovedá tabuľke vyššie:

```php
use RoundlyConsulting\Lifecycle\Definition\LifecycleBuilder;
use RoundlyConsulting\Lifecycle\Definition\LifecycleDefinition;
use RoundlyConsulting\Tickets\Contracts\TicketLifecycle;
use RoundlyConsulting\Tickets\Enums\Automation;

final class SupportLifecycle extends LifecycleDefinition implements TicketLifecycle
{
    public function define(LifecycleBuilder $lifecycle): void
    {
        $lifecycle->states(SupportStatus::class)->initial(SupportStatus::Triage)->terminal(SupportStatus::Done);
        // … transitions, stamps, a Resolved-category TTL …
    }

    public function automation(Automation $hook): ?string
    {
        return match ($hook) {
            Automation::Assigned => 'accept',
            Automation::RequesterReplied => 'resume',
            Automation::RequesterReopened => null,     // off
            Automation::AutoClose => 'archive',
            Automation::Merged => 'discard',
        };
    }
}
```

Kontrakt sa overuje lenivo — pri prvom prechode alebo automatizácii, s cache na triedu —, takže chybný cyklus nikdy nerozbije artisan. Porušenie vyhodí InvalidTicketLifecycleException a tickets:doctor nahlási každý problém: not\_a\_definition, not\_status\_attribute, state\_not\_ticket\_state, automation\_unknown, automation\_not\_system, automation\_source, automation\_target plus vlastné problémy validácie lifecycle (lifecycle.<code>). withStatusCategory() aj každé pravidlo podľa kategórií sa riadia nakonfigurovaným enumom.

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/tickets-for-laravel.md)
