Odpovede a interné poznámky
Konverzácia tiketu je vlákno comments-for-laravel na tikete. Tickets zapisuje každú správu cez comments a pridáva blok meta vo vlastnom mennom priestore — vaše vlastné kľúče meta zostanú vedľa neho a kľúč hostiteľa nikdy nemôže podvrhnúť menný priestor tickets:
comment.meta.tickets = { internal: bool, role: 'agent'|'requester'|'participant'|'system', channel: string }Správy sú koreňové komentáre (bez vnorených odpovedí): comments skryje z verejného vlákna všetko pod neviditeľným komentárom, takže verejná odpoveď pod poznámkou by zmizla.
Odpovede a poznámky
// A public reply — with an optional transition applied in the same transaction
$comment = Tickets::for($ticket)->by($agent)->reply('A technician is on the way.', transition: 'wait');
Tickets::for($ticket)->by($customer)->reply('Here is a photo.', attachments: [$request->file('photo')], channel: 'web');
// An internal note — agents only, never shown to the requester
Tickets::for($ticket)->by($agent)->note('Roller worn out, order a spare.');
// Model conveniences, through the manager
$ticket->reply('Thanks!', $customer);
$ticket->note('Escalated to vendor.', $agent);
// Edit and delete (scoped to the ticket; each left in the timeline)
Tickets::for($ticket)->by($agent)->editComment($comment, 'A technician is on the way (ETA 2 pm).');
Tickets::for($ticket)->by($agent)->deleteComment($comment);
// Read
Tickets::for($ticket)->thread(); // public: published replies, oldest first
Tickets::for($ticket)->thread(internal: true); // every message: notes and held replies tooreply() berie body, transition, attachments, channel, reason a payload (pre prechod) a meta; note() berie body, attachments, channel a meta. Obe vracajú Comment z comments. Kanál musí byť jeden z tickets.channels (predvolene tickets.default_channel).
| Aspekt | Verejná odpoveď | Interná poznámka |
|---|---|---|
| visible v comments | true | false — verejné čítania v comments ju nikdy neukážu |
meta.tickets.internal | false | true — obrana do hĺbky: komentár označený ako interný sa tak berie, aj keď ho hostiteľ zviditeľnil |
| kto | žiadateľ, agent, účastník, systém | agenti a systém |
| aktivita | replied (verejná) | note_added (interná; id komentára, nikdy text) |
| udalosť | TicketReplied (s rolou) | TicketNoteAdded |
| notifikácia | replied / requester_replied | note_added (len agenti) |
Úpravy a mazanie
editComment() a deleteComment() konajú ako aktér handlu a zapíšu záznam aktivity comment_edited / comment_deleted — id komentára a rolu autora správy, nikdy text — s rovnakou viditeľnosťou ako správa: verejný pri zverejnenej verejnej odpovedi, interný pri poznámke či zadržanej odpovedi. TicketCommentUpdated / TicketCommentDeleted sa spustia po potvrdení. Kto smie upravovať či mazať, rozhoduje policy API (updateComment / deleteComment); PHP API sa nepýta.
Roly autorov
Určia sa pri odoslaní správy:
| Autor | Rola |
|---|---|
| žiadateľ tiketu | requester |
| agent pre tento tiket (oprávnenie agenta zúžené cez AgentScope) | agent |
| sledujúci (pri tickets.watchers.can_view) | participant |
| nikto (asSystem()) | system |
| ktokoľvek iný | odmietnuté — TicketAccessDeniedException |
Agent, ktorého rozsah agentov z tohto tiketu vylúči, tu agentom nie je: odpovedá ako sledujúci, ktorým je (účastník — bez pečiatky prvej odpovede a jeho odpoveď obnoví čakajúci tiket), alebo sa odmietne. Poznámka od kohokoľvek iného ako agenta pre tento tiket vyhodí TicketAccessDeniedException. Uzavretý tiket neprijme žiadnu správu — odpovede, poznámky, úpravy aj mazanie vyhodia TicketClosedException (v API 409 ticket_closed); namiesto toho založte nadväzujúci tiket.
Čo odpoveď spustí
- Explicitné transition: sa uplatní atomicky — zamietnutý prechod nenechá žiadnu odpoveď — a nahradí automatizáciu odpovede. Uplatní sa, len keď sa odpoveď zverejní; pri zadržanej odpovedi sa jeho názov ani nekontroluje.
- Automatizácie odpovedí (len odpovede žiadateľa alebo účastníka): čakajúci tiket sa obnoví (RequesterReplied); vyriešený tiket sa znovu otvorí (RequesterReopened), keď je zapnuté tickets.comments.reply_reopens.
- Prvá odpoveď: prvá zverejnená verejná odpoveď agenta raz zaznamená first_responded_at a spustí TicketFirstResponded. Poznámky, odpovede žiadateľa a zadržané odpovede ju nikdy nezaznamenajú.
- Automatické sledovanie: agent, ktorý napíše, začne tiket sledovať (tickets.watchers.auto.agent_repliers).
- last_activity_at sa posunie pri každej odpovedi, poznámke, prechode a priradení. Posúva ho aj poznámka, preto je v API resources a radení len pre agentov a posun sa nikdy nedotkne updated_at.
Moderácia hostiteľa
| Nastavenie hostiteľa | Účinok na odpoveď na tiket |
|---|---|
| comments.require_approval zapnuté | Hneď schválená (tickets.comments.auto_approve, predvolene zapnuté). |
| comments.require_approval zapnuté a tickets.comments.auto_approve vypnuté | Zadržaná pre moderátora. |
| zhoda s blocklistom s akciou pending / hidden | Zadržaná — nikdy sa automaticky neschváli (obišlo by to filter hostiteľa). |
| zhoda s blocklistom s akciou reject | comments vyhodí CommentRejectedException a celá odpoveď sa vráti späť (API 422 comment_rejected). |
Zadržaná odpoveď nezmení nič okrem vlákna. Zostane viditeľná len pre agentov, jej aktivita replied je interná (held: true plus prechod, o ktorý žiadala) a neuplatní prechod, nespustí automatizáciu, nezaznamená prvú odpoveď, nespustí TicketReplied a nikoho neupovedomí — žiadateľ tak nikdy neuvidí zmenu stavu spôsobenú správou, ktorú nikto nemôže prečítať. Neskoršie schválenie cez comments správu len zverejní; ak prechod stále chcete, uplatnite ho sami.
Ručná moderácia zastaví tok čakanie → obnovenie: pri zapnutom comments.require_approval a vypnutom tickets.comments.auto_approve sa zadrží každá odpoveď a jej neskoršie schválenie nič nedobehne — čakajúci tiket zostane čakať, vyriešený sa znovu neotvorí, nikto nedostane notifikáciu a aktivita replied zostane interná. Zmienky z odpovede comments pri schválení doručí. Ak moderujete ručne, počúvajte CommentApproved z comments pre komentáre tiketov a spustite, čo potrebujete (Tickets::for($ticket)->resume(), notifikáciu riešiteľovi).
comments.authorization
Pri zapnutom comments.authorization (predvolene vypnuté) kontroluje comments vlastné Gate oprávnenia voči prihlásenému používateľovi pri každom príspevku, schválení, zamknutí a odomknutí — nie voči autorovi komentára. Odpovede hostí, systémové poznámky, poznámky zo zlúčenia, automatické schvaľovanie aj zamknutie pri automatickom uzavretí z plánovača potom závisia od vašej CommentPolicy a tickets:doctor upozorní. Vlastná policy balíka tickets už rozhodla, kto smie na tiket písať, preto komentované tikety pustite ďalej:
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Comments\Models\Comment;
use RoundlyConsulting\Comments\Policies\CommentPolicy;
use RoundlyConsulting\Tickets\Models\Ticket;
final class AppCommentPolicy extends CommentPolicy
{
public function create(?Model $user, ?Model $commentable = null): bool
{
return $commentable instanceof Ticket || parent::create($user, $commentable);
}
public function moderate(?Model $user, Comment $comment): bool
{
return $comment->commentable instanceof Ticket || parent::moderate($user, $comment);
}
public function lock(?Model $user, Model $lockable): bool
{
return $lockable instanceof Ticket || parent::lock($user, $lockable);
}
public function unlock(?Model $user, Model $lockable): bool
{
return $lockable instanceof Ticket || parent::unlock($user, $lockable);
}
// update() / delete() the same way, if you edit ticket messages through comments
}Zmienky
Comments rozpozná @handle a spustí CommentMentioned — len keď hostiteľ nastaví comments.mention_resolver, len pri schválenom komentári a raz na osobu. Tickets z toho urobí TicketMentioned len pre niekoho, kto smie daný komentár čítať: zmienka v poznámke zasiahne agentov, ktorým rozsah agentov povoľuje na tikete pracovať, zmienka v odpovedi vyžaduje prístup na zobrazenie. Notifikácia mentioned odíde, len ak danú osobu už nezasiahne notifikácia samotnej správy; pri zapnutom tickets.watchers.auto.mentioned začne spomenutý čitateľ tiket sledovať. Vaše vlastné listenery CommentMentioned / CommentCreated vidia aj interné poznámky — filtrujte v nich podľa meta.tickets.internal.
Prílohy správ
Prílohy odpovedí a poznámok sú prílohy komentárov: súkromná skupina príloh balíka comments na comments.media.private_disk, cez media-library. API ich servíruje cez krátkodobé podpísané URL a hosť si môže stiahnuť len súbory tiketu a jeho verejného vlákna.
Dopyty na vlákno cez comments
use RoundlyConsulting\Comments\Facades\Comments;
Comments::for($ticket)->whereMeta('tickets.role', 'requester')->get();
Comments::for($ticket)->whereMeta('tickets.internal', true)->get(); // the notesPrejavte 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 kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
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.