Shop It Docs
Developer Resourcesconsultation

Consultation Module Backend Documentation

Consultation schema, slot and booking contracts, and runtime behavior.

Consultation Module - Backend Documentation

1. Backend Scope and Boundaries

Consultation backend owns:

  • slot inventory management (admin)
  • booking creation and booking status tracking
  • customer slot discovery and customer booking history
  • consultation notification job enqueueing (email + push)

It does not own payment processing. Consultation booking is a scheduling/contact workflow backed by slot + booking tables.

2. Module Composition (Aggregate + Leaf)

ConsultationModule composes:

  • ConsultationSharedModule
  • ConsultationCustomerModule
  • ConsultationAdminAggregateModule

Admin aggregate composes leaf modules:

  • ConsultationSlotAdminModule (/admin/consultations/slots)
  • ConsultationBookingAdminModule (/admin/consultations/bookings)

Customer/mobile surface is owned by ConsultationCustomerController at @Controller("consultations") and mounted to /api/mobile/consultations through MobileModule route composition.

3. Data Model (Drizzle / PostgreSQL)

Schema source of truth:

  • packages/db/src/schema/consultation/consultation-slots.ts
  • packages/db/src/schema/consultation/consultation-bookings.ts

3.1 Tables

  • consultation_slot
    • primary key: id (serial)
    • unique: (date, start_time) via consultation_slot_date_start_uq
    • checks: consultation_slot_time_check (start_time < end_time)
    • indexes: consultation_slot_date_idx, consultation_slot_is_active_idx
  • consultation_booking
    • primary key: id (serial)
    • foreign keys:
      • slot_id -> consultation_slot.id (ON DELETE RESTRICT)
      • customer_id -> customers.id (ON DELETE SET NULL)
    • unique: slot_id via consultation_booking_slot_uq (one booking per slot)
    • checks:
      • consultation_booking_full_name_non_blank_ck
      • consultation_booking_contact_num_non_blank_ck
      • consultation_booking_email_non_blank_ck
      • consultation_booking_contacted_state_ck

3.2 Enums

  • consultation_booking_status: pending, contacted

4. Runtime Rules and Domain Invariants

4.1 Slot validity

  • Slot must exist.
  • Slot must be active to accept booking.
  • Slot date must be today or future in Nepal date context.
  • Slot time windows for creation/update must satisfy startTime < endTime.

4.2 Booking integrity

  • Slot can have at most one booking.
  • Guest booking is allowed (customer_id = null).
  • Authenticated booking links customer_id.
  • Deleting a slot with existing bookings is blocked and returns CONSULTATION_BOOKING_SLOT_RESTRICTED.

4.3 Bulk slot generation

Admin bulk create uses weekday + interval generation:

  • if startDate omitted: uses current Nepal date
  • if endDate omitted: derives end via weeksAhead (default 4)
  • if endDate provided without startDate: rejected
  • insertion uses conflict-safe onConflictDoNothing on (date, startTime)

4.4 Notifications

On booking creation, service enqueues:

  • NotificationJob.SEND_EMAIL to QueueName.NOTIFICATIONS
  • NotificationJob.SEND_PUSH to QueueName.NOTIFICATIONS when customerId exists

Queue job ids are deterministic per booking/customer for dedupe behavior.

5. Caching Strategy

AreaKey PatternTTL StrategyInvalidation Trigger
Customer slot listconsultation:customer:slots:list:CONSULTATION_SLOTS_CACHE_TTL_SECONDS (default 300)slot writes and booking creation

Implementation notes:

  • Keys use CacheKeyUtil.build(...).
  • Invalidation uses invalidatePattern(prefix*).
  • Redis failures degrade gracefully (warn + DB fallback).

6. Rate Limiting Strategy

Environment-configured limits:

  • CONSULTATION_PUBLIC_BOOK_RATE_LIMIT (default 10)
  • CONSULTATION_PUBLIC_BOOK_RATE_WINDOW_SECONDS (default 60)

Applied in controllers for:

  • customer: slots, book, bookings
  • admin: slot and booking operations

Breach behavior:

  • throws RateLimitExceededException
  • returns RATE_LIMIT_EXCEEDED

7. Error and Resilience Contracts

Representative consultation errors:

HTTPerrorCodeMessage
400CONSULTATION_SLOT_INACTIVEConsultation slot is not active.
400CONSULTATION_SLOT_PAST_DATECannot book a slot in the past.
400CONSULTATION_SLOT_ALREADY_BOOKEDSlot is already booked.
400CONSULTATION_BOOKING_SLOT_RESTRICTEDCannot delete slot that has bookings. Please deactivate instead.
404CONSULTATION_SLOT_NOT_FOUNDConsultation slot not found.
404CONSULTATION_BOOKING_NOT_FOUNDConsultation booking not found.
409CONSULTATION_SLOT_CONFLICTSlot conflict (duplicate slot or invalid slot-time window).
429RATE_LIMIT_EXCEEDEDToo many requests. Please try again later.

Resilience notes:

  • Unique/check constraints provide DB-level race protection.
  • Booking creation translates unique-slot conflict to structured domain error.
  • Cache and rate-limit Redis failures are fail-open with warning logs for availability.

8. Performance Notes

  • List endpoints use projected column selection and optional pagination paths.
  • PaginationUtil.normalize(...) and PaginationUtil.getDrizzleParams(...) are used for list contracts.
  • Count queries execute only when pagination is enabled.
  • Slot-list cache avoids repeated expensive joins for read-heavy browse traffic.

9. Backend Diagram

10. Release/QA Checklist

  • Admin slot list/detail/create/update/delete routes enforce permissions and guards.
  • Bulk slot generation date-window rules (startDate, endDate, weeksAhead) are validated.
  • Booking flow blocks inactive/past/already-booked slots with structured error codes.
  • Booking status update to contacted sets contactedAt and respects state constraints.
  • Slot cache keyspace invalidates on slot writes and booking creation.
  • Notification jobs are enqueued with deterministic job ids.
  • Mobile-composed routes under /api/mobile/consultations resolve correctly.

11. File Map

  • apps/api/src/modules/consultation/admin/*
  • apps/api/src/modules/consultation/customer/*
  • packages/db/src/schema/consultation/*

12. Environment Variables

VariableDefaultDescription
CONSULTATION_PUBLIC_BOOK_RATE_LIMIT10Rate limit for booking requests per window
CONSULTATION_PUBLIC_BOOK_RATE_WINDOW_SECONDS60Rate limit window in seconds for booking
CONSULTATION_SLOTS_CACHE_TTL_SECONDS300Cache TTL for customer slot list in seconds

Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.


See Also