> ## Documentation Index
> Fetch the complete documentation index at: https://ihub.learnille.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Consultation rescheduling and rebooking

> Internal lifecycle, ownership, payment boundaries, and frontend responsibilities for moving or repeating a consultation

**Owner:** Backend Engineering

**Last reviewed:** 2026-09-23

**Next review:** 2026-12-23

This page explains how a consultant prompts a student to move a missed session,
and how a student purchases another consultation. These are separate operations.

## Choose the correct operation

| Question | Reschedule an existing session | Rebook the consultation |
| - | - | - |
| Intent | Move a session to a replacement time | Purchase another session or recurring session set |
| Record identity | Keep the existing session ID | Create a new order, enrollment, booking, and session set |
| Earlier booking | Its session dates change when rescheduling completes | Earlier bookings and payments remain unchanged |
| Payment | Reschedule fee, if configured and applicable | Normal checkout at current pricing; zero-total orders need no payment |
| Initiator | Student selects the time; owning consultant may first send a prompt | Student or purchaser creates a new purchase |
| Approval | Owning consultant or admin approves the rescheduled session | Normal booking fulfillment; no reschedule approval step |

## Consultant-prompted rescheduling

```mermaid theme={null}
flowchart TD
    A[Missed session] --> B[Owning consultant prompts student]
    B --> C[Email and in-app notification]
    C --> D[Student selects replacement time]
    A --> D
    D --> E{Fee required?}
    E -- Yes --> F[pending_payment]
    F --> G[Backend confirms payment]
    G --> H[rescheduled]
    E -- No --> H
    H --> I[Owning consultant or admin approves]
    I --> J[scheduled]
```

1. The owning consultant calls `POST /sessions/:id/request-reschedule` with no body.
   The session must be `missed`, its booking must not be cancelled, rescheduling must
   be enabled, and the configured positive reschedule limit must not be exhausted.
   A pending reschedule payment or missing booked student also prevents prompting.
   Admin status alone does not grant permission to send the prompt.
2. The backend triggers email and in-app notifications to the booked student.
   Notification data includes `sessionId`, `consultationId`, and action
   `SESSION_RESCHEDULE_REQUESTED`. The frontend opens the rescheduling UI for that
   session and refetches its state.
3. The student submits a replacement `newStartTime` to `POST /sessions/:id/reschedule`.
   The consultant cannot select a time on the student's behalf through this endpoint.
   The student does not need to receive a prompt before rescheduling an eligible session.
4. With no fee, the backend applies the new dates immediately. With a fee, it returns
   payment information and marks the session `pending_payment`; dates change only
   after backend payment processing succeeds. Once applied, the session is `rescheduled`.
5. The owning consultant or an admin calls `POST /sessions/:id/approve-reschedule`.
   This changes `rescheduled` to `scheduled` and attempts a student approval notification.
   Approval does not select or apply another time. There is no reschedule-rejection
   endpoint or automatic restoration of the previous time in this flow.

### Rules and side effects

* Sending a prompt does not modify dates, status, attendance, payment, or the
  reschedule count. It does not reserve a slot or waive fees or cooldowns.
* Repeated successful prompt requests send repeated notifications. There is no
  prompt-specific deduplication; disable the action while submitting and do not
  blindly retry an ambiguous network error.
* The reschedule endpoint accepts `upcoming`, `scheduled`, `rescheduled`, and `missed`.
  Minimum notice for a missed session is measured against the replacement start time.
  For the other eligible statuses, notice is measured against the original start time.
* The backend checks future time, availability, ownership, reschedule limits,
  pending payments, and cooldowns. Missed sessions additionally require enabled
  rescheduling and a non-cancelled booking.
* Applying the replacement time resets attendance timestamps and `bothPartiesJoined`,
  updates the session's date and end time, replaces reminder/status/finalization jobs,
  and triggers rescheduling notifications for both participants.
* Session statuses are lowercase. The separate reschedule-record statuses are
  uppercase, such as `PENDING_PAYMENT` and `COMPLETED`.

The original session's ledger entry remains associated with that session. After both
participants attend the replacement session, finalization schedules release under
the configured hold policy. See the [completion lifecycle](https://ihub.learnille.com/engineering/architecture/consultation-session-completion-lifecycle.md)
for the payment lifecycle; a successful reschedule is not itself a payout.

## Rebooking the consultation

```mermaid theme={null}
flowchart TD
    A[Student chooses same consultation again] --> B[Select new available date and time]
    B --> C[Create new direct order or cart checkout]
    C --> D{Payment required?}
    D -- Yes --> E[Complete new payment]
    D -- No --> F[Order fulfillment]
    E --> F
    F --> G[New enrollment, booking, sessions, and ledger entries]
```

Use the existing `PRODUCT_PURCHASE` flow through `POST /orders`, directly or after
adding the consultation to the cart. Keep the consultation ID and recipient and
supply the newly selected date/time. No `rebook` flag or new endpoint is required.
Current pricing and availability apply; do not reuse an earlier order/payment reference
or submit a `RESCHEDULE_FEE` order for another purchase.

A prior consultation enrollment does not block another purchase, even when the prior
booking is still active. Courses keep their existing duplicate-purchase checks. The
same consultation cannot be added twice to a single cart; this change permits a new
purchase, not duplicate entries within one cart.

The backend rechecks cart slots at checkout because availability can change after
insertion. Self-booking and inactive-product checks remain in place. Fulfillment
links each new session to the enrollment for its own order, rather than an earlier
enrollment for the same student and consultation. Processing the same order item
again must not create another booking or credit.

For recurring consultations, the purchase creates a new session set using the
configured recurrence. If explicit `metadata.requestedStartTimes` are supplied, they
must contain the replacement purchase's dates rather than old session dates.

### Frontend integration responsibility

`GET /enrollment/check/:productType/:productId` returns `isEnrolled` and `canPurchase`.
For consultations, both can be true. The frontend must use `canPurchase` to gate the
booking action, scheduling page, and checkout. Existing clients that block whenever
`isEnrolled` is true will continue to prevent rebooking until updated.

Purchase eligibility is not a reservation or an availability guarantee. Enrollment
information keeps its existing meaning; the backend does not hide old enrollments
just to enable checkout. Read these fields from HTTP `data` unless the API client
already unwraps the standard response envelope.

## Sources of truth and verification

Detailed request/response contracts belong in the separate API documentation:

* [Reschedule consultation API flow](https://docs.learnille.com/flows/reschedule_flow)
* [Rebooking integration guide](https://docs.learnille.com/flows/booking_frontend_integration#rebooking-a-consultation)

Their source files are `docs/flows/reschedule_flow.mdx` and
`docs/flows/booking_frontend_integration.mdx` in the sibling API docs repository.
Published pages reflect these changes only after that repository is deployed.

Backend implementation references (paths within the server repository):

* `src/consultation/sessions.controller.ts` and `sessions.service.ts`: prompt,
  reschedule, approval, attendance, and completion.
* `src/cart/cart.service.ts` and `src/order/order.service.ts`: repeat purchases and
  checkout validation.
* `src/consultation/consultation.service.ts`: separate booking/session fulfillment
  and order-scoped enrollment linking.
* `src/enrollment/enrollment.controller.ts`: purchase-eligibility response.

See the [verification checklist](https://ihub.learnille.com/engineering/testing-and-qa/consultation-rescheduling-and-rebooking.md).
Unit-test success does not establish live email delivery, payment callback handling,
queue execution, or payout completion. Deployment and frontend integration must be
verified separately before treating the user journey as released.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.