Agency Flow · Documentație Services & Billing

Zece billing types, aceeași schemă lunară

Un serviciu are exact un billing type; tipul e un strategy pattern — schema stochează parametrii, codul calculează, DB-ul păzește derivatele. Documentația de aici arată schema completă plus câte un flux narativ pas-cu-pas pentru fiecare tip: cine acționează, ce se inserează, ce se calculează și când îngheață fiecare cifră.

Account manager — setup Engine — automat Specialist / Echipa Finance — fee & facturare
Setup UI decision · 2026-07-10. Din pagina Digital Asset, Add service deschide drawerul comun direct pe A1. Billing Type rămâne selectabil în drawer și încarcă formularul Symfony dedicat tipului ales; schimbarea resetează Supplier/pricing fără confirmare, dar păstrează detaliile comune. Currency este setată per serviciu și se blochează doar în Budget mode. Asset și Composed name sunt evidențiate ca valori read-only, iar Composed name ocupă un rând complet și rămâne pe o singură linie. Pentru Provider Stack, după salvare se reîmprospătează doar panoul Services, astfel încât editările nesalvate rămân intacte. Fără JavaScript, selectorul grupat și rutele concrete rămân fallback-ul complet funcțional.
Exact Service end · 2026-07-14. end_date este ultima zi activă inclusivă. Setarea, schimbarea sau anularea unei date viitoare folosește ServiceEndScheduler: verifică intervalul complet al identității sub lock-ul Digital Asset-ului, protejează istoricul financiar și reconciliază atomic doar lunile a căror acoperire exactă s-a schimbat. Data rămâne editabilă în ultima zi activă, apoi Service-ul Closed este imuabil; minimul ultimei luni facturate este impus server-side, iar o veche lună finală viitoare nereprezentată nu se materializează dincolo de orizontul de referință.
Exact calendar UI · 2026-07-14. Formularele folosesc Paused from, Last paused day, Resume on și ruta POST /services/{serviceId}/end-date pentru Last active day. Stările sunt derivate dintr-un ClockInterface injectat. Dashboard-ul afișează auditul exact al pauzelor, intervalul calendaristic și baza de zile a fiecărei perioade, ecuațiile A1/C/D din inputurile fixe persistate pe perioadă și ecuațiile A2/B din billed hours plus rate/cap înghețate. Dacă orele labour se actualizează după ready, ultimul total eligibil apare separat. UI-ul nu reconstruiește ecuații din default-uri curente mutabile; rândurile legacy facturate fără bază sau fără inputurile de calcul obligatorii afișează Historical calculation. Înghețarea este per ServiceBillingPeriod, nu per Service și nu per formular TimeEntry: după ready se pot adăuga pontaje întârziate, care mișcă labour-ul/profitabilitatea până la invoicing fără să modifice suma client sau ecuația facturabilă înghețată; includerea lor pe factură cere reopen/recompute explicit.
Post-migration calendar reconciliation · 2026-07-14. app:billing:reconcile-calendar [--tenant=<uuid>] repară numai lunile deja reprezentate de perioade sau billing pauses. Comanda precolectează perechea Service/Digital Asset, blochează asset-ul înainte să încarce Service-ul fresh și rulează fiecare Service într-o tranzacție izolată: rândurile nefacturate primesc baza de zile, snapshot-urile și liniile generate lipsă, starea ready își păstrează timestampul și ajustarea manuală, iar invoiced rămâne neatins. Coverage zero nu șterge override-uri manuale sau linii deliverable user-owned, iar coverage zero/parțial nu exclude pontaje datate; conflictele sunt detectate înainte de mutații UnitOfWork și raportate skipped fără să oprească celelalte Servicii. Ordinea de deploy: migrarea Doctrine, comanda de reconciliere, apoi generarea normală.

HIBRID Supplier și labor deodată

Singura excepție de la regula labor-XOR-supplier: financiar de platformă plus orele echipei care o administrează.

Cum se citește orice flux: pasul 1 e mereu setup-ul (2 rânduri: service + tabelul de pricing al tipului), pasul 2 e deschiderea lunii (rândul de perioadă), la mijloc stă diferența specifică tipului (ore / cost / linii / spend), iar finalul e identic: facturare din snapshot, înghețare, raportare prin SUM. Ce diferă între tipuri e doar cine completează ce, pe aceleași locuri.