NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Approvals for Laravel

Rozhodnutia a stavy

Každé rozhodnutie je riadok Approval medzi aktérom a schvaľovaným modelom. Nesie explicitný stav — pending, approved, rejected, cancelled alebo expired — plus voliteľný dôvod, voliteľnú expiráciu, váhu a čas rozhodnutia.

Životný cyklus rozhodnutia

use RoundlyConsulting\Approvals\Facades\Approvals;

// 1. Ask for a decision — records a pending row.
Approvals::for($contract)->as($legal)->ask();
Approvals::for($contract)->hasPending();              // true

// 2. The same actor decides — the pending row becomes approved.
Approvals::for($contract)->as($legal)->because('Clauses reviewed')->approve();
Approvals::for($contract)->as($legal)->isApproved();  // true

// 3. Changed their mind — the approval is withdrawn (cancelled), only the rejection counts.
Approvals::for($contract)->as($legal)->because('New revision uploaded')->reject();

// 4. Or withdraw the live decision without replacing it.
Approvals::for($contract)->as($legal)->cancel();      // status: cancelled

Jedno živé rozhodnutie na slot

Každý aktér má na jeden slot jedno živé rozhodnutie — samostatné rozhodnutie o schvaľovanom modeli alebo rozhodnutie v jednej žiadosti (či v jednom stupni viacstupňovej žiadosti). Nové rozhodnutie to pôvodné zmení, nepridá druhé: dvojité schválenie nič nezmení a zamietnutie po schválení schválenie stiahne (jeho stav bude cancelled), takže sa počíta len zamietnutie — a naopak.

Slot stráži unikátny index v databáze, takže dve súbežné schválenia toho istého aktéra sa započítajú raz. Nová žiadosť alebo ďalší stupeň je nový slot: schválenie staršej žiadosti vám nikdy nezabráni schváliť ďalšiu.

Povolené prechody

Stavy sa menia cez strážený stavový automat. Rozhodnuté schválenie či zamietnutie sa dá ešte zrušiť — stiahnuť alebo nahradiť, keď aktér zmení názor — a schválenie vyprší, keď mu uplynie platnosť. Zrušené a expirované sú koncové stavy:

Zo stavuMôže prejsť do
pendingapproved, rejected, cancelled, expired
approvedcancelled (stiahnuté alebo nahradené), expired (po uplynutí platnosti)
rejectedcancelled — stiahnuté alebo nahradené
cancelled / expirednikam — koncové stavy
use RoundlyConsulting\Approvals\Enums\ApprovalStatus;

ApprovalStatus::Pending->canTransitionTo(ApprovalStatus::Approved);    // true
ApprovalStatus::Approved->canTransitionTo(ApprovalStatus::Cancelled);  // true — withdrawn or superseded
ApprovalStatus::Approved->canTransitionTo(ApprovalStatus::Expired);    // true — lapses once its expiry passes
ApprovalStatus::Rejected->canTransitionTo(ApprovalStatus::Cancelled);  // true — withdrawn or superseded
ApprovalStatus::Approved->canTransitionTo(ApprovalStatus::Rejected);   // false — a change of mind writes a new decision
ApprovalStatus::Cancelled->canTransitionTo(ApprovalStatus::Approved);  // false — terminal

Prechodové metódy na modeli Approval — approve(), reject(), cancel() a markExpired() — overia každý krok a pri nepovolenom vyhodia InvalidStatusTransitionException.

Čo robí ktoré volanie

  • approve() — zapíše schválenie do slotu aktéra. Čakajúce vyžiadanie sa rozhodne priamo, držané zamietnutie sa nahradí a zapíše sa nové schválenie. Opätovné schválenie vráti to isté schválenie a nespustí žiadne udalosti.
  • reject() — zrkadlovo: čakajúce vyžiadanie sa rozhodne priamo a držané schválenie sa stiahne, takže sa počíta len zamietnutie. Zamietnutie nemá expiráciu, preto expirácia nastavená pred reject() vyhodí InvalidApprovalRequestException.
  • ask() — zapíše čakajúce rozhodnutie pre aktéra, adresované práve tomuto modelu, nikdy tomu, koho zastupuje, s because() ako dôvodom vyžiadania a expiráciou ako termínom na odpoveď. Ak už aktér v slote živé rozhodnutie má, vráti ho nezmenené. weight() odmietne — váhu nesie až odpoveď.
  • cancel() / cancelApproval() — stiahne živé rozhodnutie aktéra (čakajúce, schválené alebo zamietnuté), prípadne to, ktoré urobil ako zástupca, kým toto delegovanie ešte platí, v tom istom kole, kam by smerovalo rozhodnutie — pri viacstupňovej žiadosti len v otvorenom stupni. because() sa stane dôvodom stiahnutia; weight() či expiráciu odmietne. Vráti stiahnuté rozhodnutie, alebo null, ak nie je čo stiahnuť.
  • toggle() / toggleApproval() — jednoduchý palec hore, nižšie.

Pri uzavretej žiadosti vyhodia ClosedApprovalRequestException — bez účinku zostane len zopakovanie schválenia či zamietnutia, ktoré tam aktér už má (pozri Žiadosti pre viacerých schvaľovateľov). Metódy traitu GivesApprovals — approve(), reject(), cancelApproval() a toggleApproval() — sú skratkou pre tie isté volania fasády. Nastavenie, ktoré volanie nevyužije, sa odmietne, nie zahodí — celý prehľad nájdete v časti Fluentné buildery.

Dôvody

Odpoveď na vyžiadanie rozhodne riadok vyžiadania priamo a zapíše len vlastný dôvod: approve(), reject() či zapnutie prepínača bez because() neuložia žiadny, s because() uložia ten zadaný. Dôvod vyžiadania zostane v udalosti ApprovalRequested a na riadku, kým na vyžiadanie niekto neodpovie. Stiahnutie nie je samostatné rozhodnutie, preto si bez vlastného dôvodu ponechá dôvod rozhodnutia — cancel() či vypnutie prepínača bez because(), rozhodnutie nahradené zmenou názoru aj vyžiadanie zrušené po uzavretí kola. Zopakovanie rozhodnutia, ktoré aktér už má, nezmení nič, ani dôvod.

Rovnako sa správajú prechodové metódy modelu Approval: approve($reason) a reject($reason) zapíšu $reason presne tak, ako ho dostanú (null dôvod vyžiadania vymaže), cancel($reason) ho nahradí, len ak je zadaný, a markExpired() ho nechá tak. Pred verziou 1.2.3 si odpoveď bez dôvodu ponechala dôvod vyžiadania, takže schválenie mohlo znieť „Please review…“.

Čítanie rozhodnutia

$approval = Approvals::for($deployment)->as($user)->because('LGTM')->approve();

$approval->status;           // ApprovalStatus::Approved
$approval->reason;           // 'LGTM'
$approval->decided_at;       // CarbonImmutable
$approval->expires_at;       // ?CarbonImmutable
$approval->weight;           // int — 1 unless weighted
$approval->actor;            // the model whose decision this is
$approval->approvable;       // the model decided on
$approval->approvalRequest;  // ?ApprovalRequest it counts toward
$approval->stage;            // ?ApprovalRequestStage, for staged requests
$approval->wasDelegated();   // bool — decided by a delegate

Jednoduchý prepínač

Zapnutie a vypnutie jedným klikom pre lajky, odporúčania či schvaľovanie jedným recenzentom:

Approvals::for($deployment)->as($user)->toggle(); // true  — approved (status: approved)
Approvals::for($deployment)->as($user)->toggle(); // false — withdrawn (status: cancelled, soft-deleted)

// Pinned to one round, with a reason — the approval's when it turns on, the withdrawal's when it turns off
Approvals::for($release)->as($lead)->within($request)->because('LGTM')->toggle();

$user->toggleApproval($deployment);                // the same through the GivesApprovals trait

Zapnutie je approve() — platí autorizačná kontrola, menovaní schvaľovatelia žiadosti, delegovanie aj kolo, do ktorého smeruje, a s nimi because(), weight() a expirácia; zamietnutie, ktoré držíte, sa nahradí. Vypnutie stiahne vaše živé schválenie, mäkko ho zmaže a rovnako ako cancel() spustí ApprovalCancelled, pričom because() poslúži ako dôvod stiahnutia; weight() ani expirácia sa nemajú na čo uplatniť. within() pripne prepínač ku konkrétnemu kolu: kolo iného subjektu vyhodí InvalidApprovalRequestException a uzavreté kolo ClosedApprovalRequestException — aj keď je otvorené neskoršie kolo. Oba smery spustia ApprovalToggled aj ApprovalStatusChanged — ak počúvate na ApprovalCancelled aj ApprovalToggled, dajte pozor, aby ste vypnutie nespracovali dvakrát.

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

Odoslaní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.