CRMconnect Azuvio · Docs

Workflow: Catering Order — De la Cerere la Factură

Module implicate: Catering (Events · Menus · Items · Packages · Staff · Ingredients) · Estimates · Invoices · Projects
Cine îl folosește: Catering Manager · Chef · Event Coordinator · Financiar
Durata tipică: Cerere → Confirmare = 1–7 zile · Eveniment = 1 zi · Facturare = imediat după eveniment

Overview

Modulul Catering Management acoperă întregul ciclu al unui eveniment de catering: de la cererea inițială (enquiry), prin configurarea meniului și a pachetului, confirmarea, execuția evenimentului cu asignare staff, până la generarea ofertei și facturării.

Calculul intern de costuri și marje (cost ingrediente vs. preț vânzare) este disponibil, dar vizibil exclusiv utilizatorilor cu permisiunea specială catering_view_costs.

Depozit (Warehouse): Modulul are propriul sistem intern de ingrediente (catering_ingredients) cu stocuri de referință. Nu se integrează cu modulul Warehouse core — scăderile de stoc nu se fac automat la executarea evenimentului.

Nu există flux de aprobare automat. Orice staff cu permisiunea catering_events → edit poate schimba statusul evenimentului la orice valoare, fără gate logic.


Diagrama fluxului

[SETUP — admin, o singură dată]
  │
  ├── Event Types (categorii evenimente: Nuntă, Corporate, Conferință etc.)
  ├── Dietary Types + Allergens (referințe nutriționale per produs)
  ├── Menu Categories (ierarhice) + Menu Sections (grupuri în meniu)
  ├── Ingredients (cu avg_cost_per_unit, stock_on_hand, reorder_level)
  ├── Menu Items (cu unit_cost, unit_price, dietary types, allergens, ingrediente)
  ├── Template Menus (colecții de items grupate pe secțiuni)
  ├── Packages (bundle fix cu qty_per_guest per item, min/max guests)
  └── Staff Roles (Head Chef, Chef, Server, Bartender, Manager, Driver — 6 sedate implicit)
  │
  ↓
[1. CERERE (Enquiry)]
  │
  ├── Catering → Events → New Event
  ├── Câmpuri obligatorii: event_name, event_type_id, event_start, event_end
  ├── Client: client_id (client existent) SAU lead_id (prospect)
  │     ⚠ Estimate/Invoice se pot genera DOAR dacă există client_id, nu lead_id
  ├── guest_count_expected: număr estimat invitați
  ├── Venue: venue_name, venue_address
  ├── Opțional: create_project=1 → creează automat un proiect legat de eveniment
  └── Status inițial: enquiry
  │
  ↓
[2. CONFIGURARE MENIU]
  │
  ├── Events → {event} → Menu tab → Assign Menu / Package
  ├── Selectare template menu SAU package
  ├── Pricing mode:
  │     ├── per_person: preț × guest_count_expected per item
  │     ├── fixed: preț fix total
  │     └── package: preț din package (price_per_person × guests)
  ├── Câmpuri suplimentare: multiplier (markup), weekend_surcharge, notes
  ├── Items din template se copiază în catering_event_menu_items
  │     (snapshot cu version curentă a item-ului + dietary/allergen snapshot JSON)
  └── Orice modificare a items → înregistrată în catering_event_menu_history
  │
  ↓
[3. GENERARE OFERTĂ]
  │
  ├── Events → {event} → butonul Generate Estimate
  ├── Crează automat un Estimate standard în CRM cu linii:
  │     ├── Headers de secțiune (qty=0, rate=0)
  │     ├── Linii items: qty = guest_count_expected, rate = unit_price
  │     └── Linii manoperă staff: qty = hours, rate = hourly_rate
  ├── estimate_id salvat pe eveniment
  ├── Status event: enquiry → quoted
  └── Estimatul poate fi editat, trimis clientului, semnat
  │
  ↓
[4. CONFIRMARE]
  │
  ├── Client acceptă oferta
  ├── Status event: quoted → confirmed (schimbat manual de staff)
  └── Opțional: asignare staff pentru eveniment (shift, rol, ore estimate)
  │
  ↓
[5. EXECUȚIE EVENIMENT]
  │
  ├── Status event: confirmed → in_progress
  ├── Staff asignați văd rolul și tura
  ├── Status staff assignments: pending → confirmed/declined → completed
  └── Note interne: catering_event_notes (visible_to_client opțional)
  │
  ↓
[6. FINALIZARE + FACTURARE]
  │
  ├── Status event: in_progress → completed
  ├── guest_count_final completat (numărul real de invitați)
  ├── Events → {event} → butonul Convert to Invoice
  │     → calls Estimates_model::convert_to_invoice(estimate_id)
  │     → invoice_id salvat pe eveniment
  └── Factura urmărită și plătită standard în Invoices
  │
  ↓
[FINANCIAR INTERN — opțional, vizibil cu catering_view_costs]
  │
  ├── calculate_event_financials(): calculează P&L intern:
  │     ├── menu.total_cost = qty × unit_cost per item
  │     ├── menu.total_revenue = qty × unit_price per item
  │     ├── labor.total_cost = hours × hourly_rate per staff
  │     └── summary: net_profit, profit_margin
  └── Vizibil DOAR cu permisiunea catering_view_costs

[EVENIMENT FACTURAT ✓ · P&L CALCULAT ✓]

Pas cu pas

1. Configurare inițială (admin)

Ordinea de configurare:

1a. Event Types

Unde: Catering → Settings → Event Types → Add

Fiecare tip are culoare de fundal și text (pentru calendar). Cel puțin un tip este necesar la crearea unui eveniment.

1b. Dietary Types și Allergens

Unde: Catering → Settings → Dietary Types / Allergens

Referințe nutriționale (gluten-free, vegan, halal etc.) și alergeni (nuci, lactate etc. — cu severity: mild/moderate/severe). Se atașează la Menu Items.

1c. Menu Categories (ierarhice) și Sections

Unde: Catering → Settings → Categories / Sections

Categories sunt ierarhice (parent_id). Sections grupează items în cadrul unui meniu (ex: „Aperitive", „Fel principal", „Desert").

1d. Ingredients

Unde: Catering → Ingredients → Add

Câmp Descriere
name Denumire ingredient
unit Unitate de măsură
avg_cost_per_unit Costul mediu per unitate
stock_on_hand Stoc disponibil (referință — nu scade automat)
reorder_level Nivel de reaprovizionare (alertă vizuală)
supplier_id Furnizorul (din catering_suppliers)

1e. Menu Items

Unde: Catering → Menu Items → Add

Câmp Descriere
item_name Denumire produs
category_id Categoria
unit_cost Cost per porție (ingredient cost)
unit_price Preț de vânzare per porție
default_portion_size Mărimea porției
prep_time_minutes Timp de preparare

Version control: Dacă unit_cost sau unit_price se modifică, version se incrementează automat. Snapshot-ul la momentul asignării pe eveniment este salvat în item_version pe catering_event_menu_items.

Adăugați dietary types, allergens și ingredients (cu qty_per_portion) pe fiecare item.

1f. Template Menus și Packages

Menus (Catering → Menus → Add): colecție de items organizați pe secțiuni. La asignare pe eveniment, items se copiază cu snapshot.

Packages (Catering → Packages → Add):

Câmp Descriere
package_name Denumire pachet
price_per_person Preț per persoană
min_guests / max_guests Număr invitați minim/maxim
Items Adăugați cu qty_per_guest per item

1g. Staff Roles

Unde: Catering → Settings → Staff Roles

6 roluri sedate implicit: Head Chef ($45/h), Chef ($35/h), Server ($25/h), Bartender ($30/h), Manager ($40/h), Driver ($20/h). Adăugați roluri personalizate cu default_hourly_rate.


2. Crearea evenimentului

Unde: /admin/catering_management_module/events → New Event

Câmpuri cheie:

Câmp Obligatoriu Descriere
event_name Da Denumire eveniment
event_type_id Da Tipul evenimentului
event_start / event_end Da Data și ora start/final
client_id Recomandat Client existent (necesar pentru generare estimate/invoice)
lead_id Alternativă Lead (fără posibilitate de generare documente financiare)
guest_count_expected Da Număr estimat invitați (folosit la calculul pricing per_person)
venue_name / venue_address Da Locația evenimentului
dietary_notes / allergen_summary Nu Note dietetice generale ale evenimentului
create_project Nu 1 = crează automat un proiect CRM legat

3. Statusurile evenimentului

Status Semnificație Tranziție
enquiry Cerere inițială → quoted la generare estimate
quoted Ofertă generată și trimisă → confirmed la acceptare
confirmed Booking confirmat → in_progress la data evenimentului
in_progress Evenimentul se desfășoară → completed la finalizare
completed Eveniment finalizat → generare factură
cancelled Anulat (terminal)
lost Pierdut (terminal)

Toate tranzițiile sunt manuale — orice staff cu catering_events → edit poate seta orice status.


4. Asignare staff pentru eveniment

Unde: Events → {event} → Staff tab → Add Staff

Câmp Descriere
staff_id Angajatul asignat
role Rolul la eveniment
shift_start / shift_end Tura de lucru
hours Ore totale (calculate automat din shift_start/end)
hourly_rate Tarif orar (pre-populat din Staff Role)

Statusuri asignare: pendingconfirmed / declinedcompleted

Detecție conflicte: Sistemul verifică automat dacă staff-ul are asignare suprapusă (check_scheduling_conflicts()) înainte de salvare.

Notificarea staff-ului: notify_all_staff() există în cod dar nu trimite email — doar loghează în activity log. Notificați staff-ul manual.


5. Generare ofertă și factură

Generare ofertă: Events → {event} → buton Generate Estimate

Estimatul creat include:

  • Headers de secțiune (pentru organizare vizuală)
  • Linii de produse: qty = guest_count_expected, rate = unit_price per item
  • Linii de manoperă: qty = hours, rate = hourly_rate per staff asignat

Estimatul apare în /admin/estimates și poate fi editat, trimis și semnat ca orice ofertă standard.

Conversie la factură: Events → {event} → buton Convert to Invoice (disponibil după Generate Estimate)

Apelează Estimates_model::convert_to_invoice($estimate_id) → factură standard în /admin/invoices.


6. Calcul P&L intern

Disponibil exclusiv cu permisiunea catering_view_costs:

Metric Calcul
menu.total_cost unit_cost × portion_per_guest × guest_count_expected per item
menu.total_revenue unit_price × portion_per_guest × guest_count_expected per item
labor.total_cost hours × hourly_rate per staff asignat
net_profit total_revenue - total_cost - labor_cost
profit_margin net_profit / total_revenue × 100

Cheltuielile externe (expenses.total_cost) sunt placeholder în cod — nu sunt implementate. Costurile externe nu se pot adăuga direct în calcul P&L.


Permisiuni necesare

Permisiune Acces
catering_events → view/create/edit/delete Gestionare evenimente
catering_menus → view/create/edit/delete Template menus
catering_menu_items → view/create/edit/delete Produse catering
catering_packages → view/create/edit/delete Pachete
catering_categories → view/create/edit/delete Categorii
catering_allergens / catering_dietary_types Date nutriționale
catering_view_costs Vizualizare costuri și marje P&L
estimates → create Generare ofertă din eveniment
invoices → create Conversie la factură

Gotchas

Problemă Cauză Soluție
Butonul Generate Estimate nu apare client_id lipsă (evenimentul are doar lead_id) Convertiți lead-ul în client și actualizați evenimentul cu client_id
Prețul pe ofertă e greșit unit_price pe item s-a schimbat după asignare Modulul face snapshot la asignare — folosiți Regenerate Estimate pentru a prelua prețurile curente
Staff-ul nu apare în dropdown Nu există Staff Roles configurate Adăugați cel puțin un Staff Role
Stocul de ingrediente nu scade Comportament corect — stocul e referință, nu transactional Deduceți manual din stock_on_hand după eveniment
P&L nu se vede Lipsă permisiune catering_view_costs Acordați permisiunea specifică rolului
Notificarea staff-ului nu funcționează notify_all_staff() nu trimite email în mod real Notificați manual staff-ul sau folosiți notificările standard CRM

Referințe module

  • Estimates — oferte generate din evenimente
  • Invoices — facturi generate din evenimente
  • Projects — proiect legat opțional la eveniment
  • Catering — documentație modul
Tip

Construiți pachete de meniu reutilizabile cu prețuri fixe per persoană înainte de rezervarea oricăror evenimente — atașarea unui pachet la un eveniment durează secunde și asigură prețuri consecvente pentru evenimente similare fără a reintra meniuri de la zero.

Note

Marcajele de alergeni pe elementele de meniu trebuie menținute înainte de construirea meniurilor. Datele incomplete despre alergeni pe articolele servite reprezintă un risc de conformitate — construiți și verificați lista principală de alergeni înainte ca orice operație de catering să fie lansată cu meniuri vizibile clienților.