Scenarii end-to-end

Notă despre „raportul de tură" invocat în scenariile de mai jos: toate mențiunile se referă la snapshotul retrospectiv creat atunci când role_horeca_manager_tura apasă Închide tura din tab-ul HoReCa → Reports (o singură dată la sfârșitul zilei, per POS). Nu există o „tură deschisă" automat; până la închidere activitatea trăiește în Comenzi + Bonuri, iar apăsarea butonului agregă retroactiv datele zilei (calendar-date × POS). Snapshotul este imuabil odată scris; re-închiderea aceleiași perechi date+POS creează un folder duplicat, nu îl suprascrie. HoReCa shift ≠ MCR Z-shift (rapoartele Z ale casei de marcat sunt artefacte separate). Pentru mecanica completă a rapoartelor (Închidere tură, Roll-up lunar, Împărțire bacșiș chelneri, Detectare anomalii pierderi) → Rapoarte tură. Permisiunea necesară: HORECA_REPORT__SHIFT_CLOSE (opțional scoped :POS:<pos-id>).

Scenariu 1 — Masa progresivă (3 valuri)

19:42  Maria deschide Masa 5 — 4 persoane
19:44  Val 1:  2× Pizza Margherita, 1× Salată Greacă, 1× Apă
       → 3 bonuri (kitchen-hot ×2 pizza, kitchen-cold ×1 salată, bar ×1 apă)
       → Bonurile rulează în paralel (pizza ~14 min, salată ~5 min, apă rapid sincronizată)

19:50  Salata gata → Maria livrează
19:51  Apa livrată
19:58  Pizzas gata → Maria livrează ambele

20:15  Familia mai vrea: 2× Tiramisu, 1× Cafea, 1× Ceai
       → 2 bonuri (dessert ×2 tiramisu, coffee ×1 cafea, ×1 ceai)
       → Maria deschide Comanda 5 din meniul "active", adaugă rândurile, Trimite

20:22  Tiramisu gata, Maria livrează
20:23  Cafea + ceai livrate

20:35  Familia mai vrea: 2× Limoncello (tradițional la final)
       → 1 bon (bar)

20:39  Limoncello servit

20:50  Familia cere nota
       → Maria atinge "Cere nota" → Comanda → pending-bill

20:51  Tatiana (casier) deschide pos-fiscal → Încasează comandă → Masa 5
       → Coș pre-populat cu toate cele 11 linii
       → Total: 1.245 MDL
       → Familia plătește: 800 MDL cash + 445 MDL card
       → Bon fiscal emis, e-Factura nu (fără cerere)
       → Comanda 5 → plătită

20:51:03  Masa 5 devine liberă în harta sălii

Pas cu pas — deschidere Comandă + adăugare produs

Ghid vizual pentru cele două acțiuni-cheie ale primului val (deschidere Comandă + adăugare prima linie). Restul fluxului (Send la bucătărie, marcare Ready, incasare fiscală) se comportă identic pentru fiecare val ulterior.

1. Deschiderea Comandei

Tab Orders

New order form gol

Formular completat

Cursor pe butonul Open

Comandă creată — toast confirmă

2. Intrare pe Order View

Cursor pe View

Order View deschis

3. Adăugare produs pe Comandă

Add-line gol

Focus pe search

Rezultate filtrate

Cursor pe rezultat

Preview produs

Info TVA populat

Cursor pe Adaugă

Linie adăugată

4. Trimitere spre bucătărie

Cursor pe Trimite spre bucătărie

Bonuri create — toast succes

Status wip pe linie

5. Bucătarul preia + marchează Ready

Tab Kitchen

Bon în queue Kitchen

Cursor pe next-stage

Kitchen queue după avansare

6. Emitere fiscală

Cursor pe Pre-bill

Cursor pe Open in POS-Fiscal

POS-Fiscal cu coș pre-populat


Scenariu 2 — Cancel mid-prep cu pierdere

19:42  Masa 7 — Andrei (chelner) preia comanda: 1× Pizza Quattro Stagioni
19:43  Trimitere → bon kitchen-hot
19:44  Vlad (bucătar) — Acceptă
19:45  Vlad — Start (consumul ingredientelor: 250g blat, 80g sos, 120g topping mix)
19:53  Clientul anunță anularea — 8 minute după Start

       Andrei nu poate anula direct (post-prep) → cere manager_tură

19:54  Manager Andrei aprobă cancel post-prep (cu notă "client retras")
       Sistemul:
         → Marchează bonul kitchen-hot ca "anulat-cu-pierdere"
         → Generează automat bon de pierdere cu rândurile productive
           transferate ca pierdere, motiv "anulare_client" păstrat pe linie
           (ruta pe cont SNC 714 dedicat = ⚙️ planificată pentru faza 2)
         → Vlad oprește prepararea, aruncă produsul
         → Stocul rămâne decrementat (consumul deja s-a întâmplat)

19:55  Comanda Masa 7 e închisă fără încasare (anulată complet)
       Masa 7 → liberă

       În raportul de închidere (când managerul apasă Închide tura):
         subtypeTotals.writeoff: rows +1, cost ~95 MDL
         topLosses: Pizza Quattro Stagioni (dacă intră în top 10 pe qty)
         (Nota: v1 raportează pe subtipuri agregate — cod SNC + motiv per linie
          sunt ⚙️ planificate pentru faza 2.)

Butonul 👁 View — navighează la Order View parent

Fiecare bon din Kitchen tab are un buton 👁 View care navighează la Order View-ul Comandei părinte (care a generat bonul). Util pentru bucătar când vrea să vadă contextul complet: alte linii ale mesei, chelnerul care a trimis, notele custom, etc.
Pas 1 — Kitchen tab overview
Pas 2 — Cursor pe butonul 👁 View
Pas 3 — Navigat la Order View (K-11) — Comanda details, Order lines, Add line — bonul original e implicit acolo (linie cu status PENDING)

Butonul ✚ Loss

Butonul ✚ Loss (Kitchen tab, per bon production) deschide dialogul Production-tied loss care înregistrează un writeoff row în folder-ul de bon:
Pas 1 — Kitchen tab cu bon production
Pas 2 — Cursor pe butonul ✚ Loss
Pas 3 — Dialog Production-tied loss cu PRODUCT / QTY (SIGNED) / COMMENT / REASON (dropdown cu motivele configurate în POS) / APPLY STOCK DELTA NOW checkbox / SAVE LOSS button


Scenariu 3 — On-the-house / oferit clienților VIP

21:00  Masa VIP-1 — Maria (chelner) deschide comanda

21:05  Patronul îi spune Mariei: "Oferă sticla de Cabernet și
       platoul de tapas, pe contul casei"

21:06  Maria adaugă în Comanda VIP-1:
         1× Cabernet 2018 (sticlă)   → marchează "gift" cu motiv "degustare_client"
         1× Platou tapas mediu       → marchează "gift" cu motiv "degustare_client"
       Sistemul:
         → Necesită aprobare manager_tură (sumă > 50 MDL prag gratuități)

21:06  Manager Andrei aprobă → marchează ca "casă oferă VIP-1"
       Sistemul:
         → Liniile rămân pe comandă cu preț 0 MDL
         → Generează rânduri pe bonul de consum cu motiv "degustare_client"
           păstrat pe linie (atribuirea pe cont SNC 712 dedicat pentru
           gratuități = ⚙️ dezvoltabilă la cerere)
         → Trimite la divizii (vinul → bar, tapas → kitchen-cold)

21:08  Vinul deschis și servit
21:14  Tapas livrat

21:30  Familia VIP comandă restul mesei normal (preparate plătite)
22:30  Cere nota

22:31  Tatiana încasează:
         Coș pre-populat:
           - Liniile gratuite apar cu mențiunea "ofertă casă", preț 0 MDL
           - Restul liniilor cu prețuri normale
         Total fiscal: 850 MDL (fără gratuități)
         Familia plătește 850 MDL card

       Bon fiscal afișează:
         "Cabernet 2018 ............ 0.00 MDL (ofertă casă)"
         "Platou tapas .............. 0.00 MDL (ofertă casă)"
         (alternativ, configurabil: liniile gratuite să fie filtrate complet)

       În raportul de închidere:
         subtypeTotals.sell.revenue: ~850 MDL (liniile „gift" cu preț 0
           nu apar ca sumă separată — reduc pur și simplu revenue-ul)
         bills.total_revenue reflectă doar sumele efectiv facturate
         (Ofertele casei se identifică din audit-ul liniei — separarea contabilă
          pe cont 712 este ⚙️ dezvoltabilă la cerere.)

Toggle-ul gift se aplică per linie în Order View (chelner). Configurabilitatea globală (activare/dezactivare feature) se face prin SharedRef horeca-orders.gift.enabled (default ON) — vezi Configurări versionate.
Pas 1 — Order View cu 2 linii (Latte + Cappuccino), buton "⃝ gift" gri pe fiecare
Pas 2 — Cursor pe butonul gift al liniei Latte
Pas 3 — Linie Latte marcată gift (buton "🎁 gift" purple, preț 0.00, toast "Linie marcată gift 🎁")
Pas 4 — Order lines după toggle: Latte 0.00 (gift), Cappuccino 35.00, TOTAL DE PLATĂ 35.00


Scenariu 4 — Dezbatere între ospătar și client (re-fa)

20:18  Pizza Diavola gata (cu ceapă)
20:19  Maria livrează la masă
20:20  Clientul: "Eu am zis fără ceapă"

       Maria verifică în comandă: nu a notat "fără ceapă"
       → totuși, decide să o refacă (politică restaurant: client întotdeauna
         are dreptate dacă diferență < 100 MDL)

20:21  Maria atinge "Re-fa" pe bonul Pizza Diavola
       Sistemul:
         → Marchează bonul curent ca "respins client" → pierdere 95 MDL
           în subtypeTotals.writeoff cu motiv "respins_client" păstrat pe
           linie (ruta pe cont SNC 714 dedicat = ⚙️ planificată)
         → Generează bon nou kitchen-hot: Pizza Diavola, observație "FĂRĂ CEAPĂ" (boldăt vizibil)

20:21  Vlad (bucătar) — Acceptă bonul nou, vede observația
20:21  Vlad — Start (consumul ingredientelor a doua oară)
20:32  Pizza nouă gata
20:33  Maria livrează — clientul mulțumit

22:00  La nota:
         Pizza Diavola pe bon: 95 MDL (1 buc., a doua)
         Restul comenzii normal

       În raportul de închidere:
         subtypeTotals.writeoff cost +95 MDL (pizza inițială)
         Loss anomaly detection: dacă frecvența pizza-loss depășește media
           rulantă (pragul warn/alert configurabil, default 1.0σ warn /
           2.0σ alert, min 0.5σ) apare în Reports → Loss anomalies
         (Un tablou dedicat „re-fa" agregat pe săptămână nu există astăzi —
          analiza se face prin filtrarea folder:invoice writeoff pe MPN +
          comentariu. Separarea pe motiv per linie e ⚙️ planificată.)

Nu există astăzi un buton dedicat "Re-fa" în UI. Fluxul de re-preparare cu pierdere se face manual în 2 pași:

  1. Chelnerul (sau bucătarul) apasă ✚ Loss pe bonul curent din Kitchen tab, motiv = respins_client, comentariu cu detalii (ex: "cu ceapă, cerută fără").
  2. Chelnerul revine în Order View + adaugă din nou linia cu produsul refuzat, ideal cu notă custom ("FĂRĂ CEAPĂ" bold) în câmpul de note al liniei (dacă activat), apoi apasă Trimite spre bucătărie.

Loss-ul intră automat în subtotalul writeoff al raportului de închidere a turei și, dacă e relevant, în Reports → Loss anomaly detection pentru monitorizare (atribuirea pe cont SNC dedicat 714 este ⚙️ planificată pentru faza 2).

Notă: un buton one-click "Re-fa" care combină cei 2 pași într-un flow ghidat (cu transfer automat al notei custom) nu e accesibil în mod implicit la moment — ⚙️ dezvoltabil la cerere.

Scenariu 5 — Bucătar refuză bon (out-of-stock)

20:45  Comanda 8 trimisă → bon bar pentru "Cabernet 2018, 1 sticlă"
20:45  Mihai (barman) — vede că s-a terminat → atinge **Refuză**
       Alege motiv: out-of-stock
       Comentariu opțional: "ultima vândută acum 5 min"

20:45:30  Maria (chelner) primește alertă: "Bon refuzat: Cabernet 2018, motiv out-of-stock"
       Maria merge la masă: "Vinul Cabernet s-a terminat, vă recomand Merlot 2019 sau
       Cabernet 2019 (similar, 50 MDL diferență)"

20:48  Clientul alege Merlot 2019
       Maria modifică comanda: șterge linia anulată, adaugă Merlot 2019, Trimite
       → Bon nou bar pentru Merlot 2019

20:49  Mihai — Acceptă, Start, Gata, Livrat

       În audit-ul bonurilor de bucătărie:
         Bonul Cabernet 2018 e marcat „anulat, motiv: out-of-stock"
           (accesibil în folder-ul bonului)
         (Raportul de închidere a turei nu are astăzi o secțiune „Refuzuri"
          agregată — bonurile anulate rămân filtrate din subtypeTotals
          prin filtrul de stage-uri finalizate. Sugestia de re-comandă
          automată nu e disponibilă.)

Butonul ↩ Anulează bon (kitchen tab, action row per bon) deschide un dialog cu motiv + notă opțională. Alertele către chelner apar în Notifications Watcher în timp real. Sugestia „re-comandă X înainte de weekend" nu e disponibilă la moment ca automatizare. Refuzurile se identifică prin audit-ul bonurilor de bucătărie anulate (fiecare bon anulat păstrează motiv + notă în folder-ul propriu); un „raport de refuzuri" agregat nu există astăzi.
Pas 1 — Kitchen tab cu bon în validated-mpns
Pas 2 — Cursor pe butonul ↩ Anulează bon
Pas 3 — Dialog "Anulează bon de bucătărie" cu Motiv + Notă opțional + butoane NU ANULA / CONFIRMĂ ANULAREA


Scenariu 6 — Personal mănâncă (masa de tură)

23:30  Manager Andrei deschide ecranul **Înregistrează consum personal**
       Selectează:
         - Vlad: 1 pizza (mică, restantă)
         - Daria: 1 salată
         - Mihai: 1 sandwich
         - Tatiana: 1 platou tapas
       Motiv: autoconsum_personal
       Notă: "Masa de tură, 23/04 seară"

       Sistemul:
         → Generează bon standalone writeoff cu motiv „autoconsum_personal"
           (motivul se stochează pe fiecare linie și e disponibil în audit)
         → Decrementează stocul ingredientelor (BOM explodat)
         → Sub prag: fără aprobare suplimentară (limita configurabilă per POS)

23:31  Confirmat → în subtypeTotals.writeoff al raportului de închidere apare
       costul agregat (~60 MDL). Separarea „Autoconsum: 4 mese" pe motiv
       este ⚙️ planificată pentru faza 2.

Consumul personal + orice altă pierdere netă de bon de bucătărie (pahar spart, stoc expirat) se înregistrează prin card-ul ✚ Standalone loss / writeoff din tab-ul Orders:
Pas 1 — Cursor pe butonul ✚ Add standalone loss
Pas 2 — Dialog Standalone loss cu PRODUCT search, QTY SIGNED (default -1), COMMENT, REASON (dropdown cu motivele configurate: anulare_client, autoconsum_personal, spart, expirat, etc.), APPLY STOCK DELTA NOW checkbox, POS selector, LINKED COMANDA optional


Scenariu 7 — Storno bon emis greșit

22:15  Tatiana emite bon fiscal pentru Masa 12: 580 MDL cash
22:16  Realizează: "Am marcat cash, dar ei au plătit card"
       → cash-ul în casă nu va corespunde

22:16  Tatiana cheamă Andrei (manager) — necesar pentru storno
22:17  Andrei aprobă storno total
       Sistemul:
         → Casierul identifică bonul greșit din audit-ul MCR și execută
           storno-ul pe casa de marcat fiscală conform procedurii SFS.
           Sistemul detectează bonul de storno la sincronizarea următoare
           cu MEV și îl loghează în auditul propriu (flux semi-asistat;
           un wizard UI ghidat pre-execuție este ⚙️ dezvoltabil la cerere).
         → Restituie cash în casă (logic, fără să dea efectiv bani — clientul a plecat)
         → Reactivează Comanda Masa 12 (din "plătită" în "pending-bill")

22:18  Tatiana re-emite bon: aceleași linii, dar metodă plată = card 580 MDL
22:18  Bon fiscal nou OK, comanda → plătită

       Vizibilitate post-storno (două artefacte separate):
         Pe raportul Z al casei de marcat (MCR sau Z sintetic pt. driver
         virtual): paymentsByType arată cash/card corect după re-emitere
           (Cash: 5.510 MDL; Card: 6.250 MDL).
         Pe raportul de închidere HoReCa: bills.count + bills.total_revenue
           reflectă bonul reemis; audit-ul storno-ului trăiește pe folder-ul
           MCR (HoReCa shift ≠ MCR Z-shift — cele două rapoarte se citesc
           împreună).
         (Un contor „Storno-uri" agregat în raportul de închidere a turei
          HoReCa nu e implementat.)

Nu există astăzi un buton "Storno" în UI-ul HoReCa sau POS-Fiscal — storno-ul e strict semi-asistat:

  1. Bonul fiscal e emis pe casa de marcat fiscală certificată (Intelect-Soft MCR sau echivalent).
  2. Storno-ul se execută manual pe casa de marcat conform procedurii SFS (buton fizic sau meniu pe MCR).
  3. Sistemul detectează bonul de storno prin sincronizarea cu SFS (device sync / MEV push).
  4. Notifications Watcher afișează evenimentele fiscale de storno în panel (⚠️ numele exact al evenimentelor rămân de reverificat în modulul de notificări).
  5. Comanda plătită se reactivează manual (necesită permisiune manager) pentru re-emitere corectă.

Comanda plătită apare în tab Billing. Reactivarea + re-emiterea sunt operațiuni distincte care necesită coordonare între manager (aprobare) și casier (execuție pe MCR).

Notă onestă: ghidarea UI vizuală (wizard pas cu pas pentru storno) nu e accesibilă în mod implicit la moment. Ce oferim: auto-detectare + logare a storno-ului efectuat pe MCR + notificare + audit inalterabil. Un flow UI ghidat pentru storno (înainte de execuție pe MCR) e ⚙️ dezvoltabil la cerere.

Concluzii

Toate aceste scenarii sunt gestionate nativ de sistem, cu:

Detalii complete → Rapoarte tură.
Pentru scenarii foarte specifice afacerii tale → discutăm la onboarding și configurăm fluxurile speciale.

Următorul pas

→ BOM & Producție sau Tarife.

sgapps.io