CRMconnect Azuvio · Docs

Workflow: Loyalty Program — Fidelizare Clienți

Module implicate: Loyalty (Rules · Transactions · Redemption · Membership · Programs) · Invoices · OmniSales · Clients
Cine îl folosește: Marketing · Sales · Customer Success
Durata tipică: Continuu — punctele se acumulează la fiecare plată

Overview

Modulul Loyalty implementează un sistem complet de fidelizare: acumulare automată de puncte la plata facturilor, trei tipuri de bonusuri suplimentare (cont nou, aniversare, manual), răscumpărare în 4 contexte diferite (factură admin, portal client, OmniSales, voucher), și un sistem de niveluri (tiere) cu beneficii diferențiate per nivel.

Condiție obligatorie: Toggle-ul global loyalty_setting trebuie setat la 1 din Setup → Marketing → Loyalty. Fără aceasta, hook-ul after_payment_added nu execută nicio logică de puncte, indiferent de regulile configurate.

Nu există expirare automată a punctelor. Punctele scad doar prin răscumpărare explicită.


Diagrama fluxului

[SETUP — admin, o singură dată]
  │
  ├── Activare globală: loyalty_setting = 1
  ├── Loyalty Rules: tip câștig (card_total / product_category / product)
  │     + benzi de răscumpărare (point_weight per bandă de puncte)
  ├── Membership Rules (Tiere): Bronze / Silver / Gold by point range
  ├── Membership Programs: discounturi per tier (card/categorie/produs)
  └── Loyalty Cards: template vizual (opțional)
  │
  ↓
[ACUMULARE PUNCTE — automat la plată]
  │
  ├── Trigger: after_payment_added → factură status = PAID (2)
  ├── Sistem caută reguli active pentru client (by client_id sau client_group)
  │
  ├── rule_base = 'card_total':
  │     puncte = poin_awarded × floor(total_factură / purchase_value)
  │     (ex: 10 puncte per 100 RON cheltuiți)
  │
  ├── rule_base = 'product_category':
  │     per linie de factură: dacă grupa produsului = rel_id în rule_detail
  │     → puncte = loyalty_point × cantitate
  │
  └── rule_base = 'product':
        per linie de factură: dacă produsul = rel_id în rule_detail
        → puncte = loyalty_point × cantitate
  │
  ├── Insert în loy_transation: type='debit', reference='order_debit'
  └── clients.loy_point += puncte câștigate
  │
  ↓
[BONUSURI SUPLIMENTARE]
  │
  ├── Cont nou (after_client_added hook):
  │     → regula cu MAX(create_account_point) activă azi
  │     → type='credit', reference='manual_credit'
  │
  ├── Aniversare (cron before_cron_run hook):
  │     → caută clienți cu câmpul custom 'Birthday' = azi (lună+zi)
  │     → o singură dată per an (verifică loy_transation.note='bonus_points_for_customers_birthday')
  │     → trimite email template 'loyalty-birthday-bonus-point'
  │
  └── Manual (admin): loyalty/transation_form → tip='credit'
  │
  ↓
[NIVEL (TIER) — calculat dinamic]
  │
  ├── client_rank() → caută loy_mbs_rule unde loy_point ∈ [loyalty_point_from, loyalty_point_to]
  ├── Cel mai înalt tier matching câștigat
  └── client_next_rank() → arată câte puncte mai lipsesc pentru nivelul următor
  │
  ↓
[RĂSCUMPĂRARE — 4 contexte]
  │
  ├── [A] Admin pe factură: câmp redeem în formularul de factură
  ├── [B] Client în portal: pagina facturii → redeem points
  ├── [C] OmniSales/POS: câmp redeem în coșul de comandă
  └── [D] Voucher/Program membership: cod voucher sau discount automat per tier
  │
  ↓
[DISCOUNT APLICAT]
  │
  ├── Puncte convertite la monedă via point_weight (ex: 1 pt = 0.05 RON)
  ├── redeemp_type='full': toate punctele, valoare calculată automat
  ├── redeemp_type='partial': clientul alege câte puncte răscumpără
  ├── Insert în loy_redeem_log: old_point, new_point, redeep_from, redeep_to
  └── clients.loy_point -= puncte răscumpărate

[CLIENT FIDEL ✓ · PUNCTE ACUMULATE ✓]

Pas cu pas

1. Activare și configurare globală (admin)

Unde: /admin/loyalty → Setup → General Settings

Activare obligatorie: loyalty_setting = 1

Fără aceasta, hook-ul after_payment_added este înregistrat dar returnează imediat fără calcul.


2. Loyalty Rules — regulile de câștig și răscumpărare

Unde: /admin/loyalty → Loyalty Rules → New Rule

O singură regulă definește atât câștigul cât și răscumpărarea.

2a. Câmpuri regulă

Câmp Obligatoriu Descriere
subject Da Denumire regulă
enable Da 1 = activă
start_date / end_date Da Intervalul de valabilitate
rule_base Da card_total / product_category / product
client_group Nu Grupul de clienți vizat (0 = toți)
client Nu ID-uri specifice de clienți (CSV)
minium_purchase Nu Valoare minimă comandă pentru câștig puncte
max_amount_received Nu Plafon maxim de puncte câștigate per tranzacție

Pentru card_total:

Câmp Descriere
poin_awarded Puncte acordate per tranșă
purchase_value Valoarea unei tranșe (ex: 100 RON = 10 puncte)

Pentru product_category și product: adăugați linii în Rule Details — fiecare linie specifică rel_type, rel_id (ID grupă sau produs) și loyalty_point per unitate.

Bonusuri speciale per regulă:

Câmp Descriere
create_account_point Puncte bonus la crearea unui cont client nou
birthday_point Puncte bonus de ziua de naștere (necesită câmpul custom 'Birthday' pe client)

2b. Benzi de răscumpărare (Redemption Tiers)

Adăugați cel puțin o bandă în secțiunea Redemption Details a regulii:

Câmp Descriere
point_from / point_to Intervalul de puncte pentru această bandă
point_weight Rata de conversie: puncte → monedă (ex: 0.05 = 1 pt = 0.05 RON)
status 'enable' = bandă activă
redeem_portal 1 = poate fi utilizată în portalul client
redeem_pos 1 = poate fi utilizată în OmniSales/POS
min_poin_to_redeem Minim de puncte necesare pentru a activa răscumpărarea
redeemp_type 'full' = răscumpărare totală · 'partial' = răscumpărare parțială

3. Membership Rules — niveluri (tiere)

Unde: /admin/loyalty → Membership → New Membership Rule

Definesc tierele (ex: Bronze, Silver, Gold) pe baza punctelor acumulate:

Câmp Descriere
name Denumire tier (ex: „Gold")
loyalty_point_from / loyalty_point_to Intervalul de puncte pentru acest tier
client_group Grupul de clienți eligibil (0 = toți)
card FK → loy_card (template card vizual opțional)

4. Membership Programs — beneficii per tier

Unde: /admin/loyalty → Membership Programs → New Program

Un program leagă un tier (sau mai multe) de un beneficiu de discount:

Câmp Descriere
program_name Denumire program
membership ID-uri tiere vizate (CSV din loy_mbs_rule)
discount Tip discount: card_total / product_category / product
discount_percent Procentul de discount
voucher_code Cod voucher opțional (pentru răscumpărare manuală)
voucher_value Valoarea fixă a voucherului
minium_purchase Comandă minimă pentru activare discount
start_date / end_date Valabilitate program

Atenție: Când un program de membership cu discount este aplicat la factură, sistemul generează automat o notă de credit (add_credit_mbs_program()) și o aplică la factură. Această notă de credit apare în modulul Credit Notes.


5. Câmpul custom „Birthday" (pentru bonus aniversar)

Unde: /admin/clients → fișa client → câmpul custom Birthday (date_picker)

Câmpul este creat automat de modul cu slug customers_birthday. Bonusul de aniversare se declanșează prin cron (before_cron_run) o singură dată pe an per client.


6. Răscumpărare puncte

6a. Pe factură (admin)

La crearea/editarea unei facturi, apare secțiunea Redeem Points dacă:

  • Clientul are puncte suficiente (≥ min_poin_to_redeem)
  • Există o regulă activă cu bandă de răscumpărare validă

Staff selectează punctele de răscumpărare → discount calculat automat → scris în loy_redeem_log.

6b. Portal client

Clientul logat vede butonul Redeem Points pe pagina facturii (dacă redeem_portal=1 pe regulă și factura nu e deja plătită complet).

Clientul alege punctele → sistemul modifică direct invoices.total (reduce totalul) și loghează în loy_voucher_inv_log.

6c. OmniSales / POS

Câmpul de răscumpărare apare în coșul OmniSales (dacă redeem_pos=1). Se aplică la crearea comenzii.

6d. Voucher membership

La introducerea unui cod voucher (apply_other_voucher filter), sistemul verifică dacă clientul aparține unui tier cu program activ care are acel cod. Returnează voucher_value și minium_purchase.


7. Vizualizare sold puncte client

Unde: /admin/clients/{id} → coloana loy_point pe fișa clientului

Soldul curent este stocat direct în tblclients.loy_point (DECIMAL). Istoricul complet al tranzacțiilor se vede în Loyalty → Transactions filtrat pe client.


Permisiuni necesare

Acțiune Permisiune
Vizualizare modul Loyalty loyalty → view
Configurare reguli, carduri, programe is_admin() exclusiv (require_loyalty_admin)
Portal client (răscumpărare) is_client_logged_in()

Gotchas

Problemă Cauză Soluție
Punctele nu se adaugă după plată loyalty_setting ≠ 1 sau regula expirată Activați toggle-ul global + verificați start_date/end_date regulii
Clientul nu apare în regula de acumulare client sau client_group nepotrivit Verificați că regula include clientul respectiv sau grupul său
Bonus aniversar nu s-a acordat Câmpul Birthday nu e completat pe client sau cron inactiv Completați câmpul + verificați cron job
Răscumpărare nu apare pe factură min_poin_to_redeem neîndeplinit sau regulă inactivă Verificați soldul punctelor vs min_poin_to_redeem
Discount membership generează notă de credit neașteptată Comportament corect — add_credit_mbs_program() Nota de credit este normală; o vedeți în Credit Notes
Puncte nu expiră Nu există mecanism de expirare Comportament corect — punctele sunt permanente; limitați prin end_date pe regulă

Referințe module

  • Clients — soldul loy_point pe fișa client
  • Invoices — răscumpărare pe factură
  • OmniSales — răscumpărare POS
  • Credit Notes — note de credit generate de membership programs
Tip

Configurați ratele de acumulare, pragurile de nivel și regulile de expirare înainte de invitarea clienților în program — schimbarea ratei de acumulare după ce clienții au acumulat solduri nu ajustează retroactiv punctele existente, creând nepotriviri de așteptări.

Note

Punctele de fidelizare se acumulează pe facturi și comenzi omnicanal. Nu se acumulează pe note de credit sau tranzacții rambursate. Revenirile parțiale sau totale ale facturilor nu reduc automat soldul de puncte existent al clientului — ajustați manual dacă este necesar.