Consultation Session Completion Lifecycle
Consultation Session Completion Lifecycle
Purpose
This document describes what happens in the backend when consultation sessions move to terminal states (done or missed), including payments, wallet availability, review gating, and testing behavior from faker.
Core Entities
consultation_sessions(ConsultationSessions): runtime session state (scheduled,ongoing,done,missed, etc.)ledger(Ledger): provider credits per consultation session, initiallyPENDINGwallet(Wallet): derived balances from ledger + withdrawalswithdrawal(Withdrawal): payout pipeline constrained bywallet.availableBalance
Lifecycle Sequence
sequenceDiagram participant F as Faker participant SS as SessionsScheduler participant S as ConsultationSessions participant E as EventEmitter participant L as LedgerService participant Q as BullMQ(FUND_RELEASE) participant FR as FundReleaseProcessor participant W as WalletService participant WD as WithdrawalAdminService
F->>S: adjustSessionTime(sessionId, hoursFromNow, triggerCompletionCheck) alt session is expired (endTime <= now - 15m) F->>SS: handleSessionCompletion() end
SS->>S: find pending sessions and detect expired alt bothPartiesJoined = true SS->>S: status = done, save SS->>E: emit consultation.session.updated SS->>E: emit consultation.completed SS->>L: findBySessionId(sessionId) SS->>L: scheduleRelease(ledgerId, holdDelay) L->>Q: enqueue release-funds job else bothPartiesJoined = false SS->>S: status = missed, save SS->>E: emit consultation.session.updated SS->>E: emit consultation.session.missed SS->>SS: send SESSION_MISSED notifications end
Q->>FR: process release-funds job FR->>L: releaseEntry(ledgerId) FR->>W: reconcileWallet(providerId)
WD->>W: getBalance(providerId, includePending=true) W-->>WD: availableBalance (released credits only)Runtime Side Effects Tied to Completion
- Session finalization:
server/src/consultation/sessions.scheduler.ts- Expired + both joined =>
done - Expired + not both joined =>
missed
- Emitted events:
consultation.session.updatedon bothdoneandmissedconsultation.completedondoneconsultation.session.missedonmissed
- Payment release:
donesessions schedule delayed fund release withPAYMENT_HOLD_DAYSmissedsessions do not auto-release
- Wallet availability:
- Only
RELEASEDledger credits contribute toavailableBalance - Withdrawals are validated against
availableBalance
- Review/completion gating:
- Consultation completion logic requires terminal sessions and at least one
done - This impacts ability to submit reviews through enrollment completion checks
- Metrics:
- Student/analytics “finished consultation” counts use
donesessions - Calendar excludes terminal statuses by default (
done,missed,cancelled,pending_payment)
Faker Testing Behavior
When calling:
POST /faker/session/:sessionId/time
with payload:
{ "hoursFromNow": -1, "triggerCompletionCheck": false}behavior is:
- Session time is shifted.
- If shifted end time is already expired (
<= now - 15 minutes) andtriggerCompletionCheckis true, faker immediately runs the same scheduler completion pass (handleSessionCompletion), so downstream effects start without waiting for cron. - Default is
false, so completion is not auto-triggered unless explicitly requested.
Notes for Deterministic Tests
- Use
hoursFromNownegative enough soendTime <= now - 15m. - Ensure
bothPartiesJoined=truebefore forcing completion if you expectdoneand release scheduling. - Use admin
POST /sessions/:id/release-fundsfor missed-session dispute resolution path.