Codebase Summary
Project: PTX Channel Manager (ptx-cm)
Version: 2.1.0
Last Updated: 2026-03-15
1. Monorepo Dependency Graph
2. Directory Structure & Metrics
| Directory | Purpose | Est. LOC | Files |
|---|---|---|---|
| apps/api | NestJS Backend | ~18,000 | 140+ TS |
| apps/web | Next.js Frontend | ~14,000 | 160+ TSX |
| packages/database | Prisma + migrations | ~900 | 10 |
| packages/types | Shared types/enums | ~500 | 5 |
| packages/config | ESLint/TS configs | ~100 | 3 |
| docs | Documentation | ~4,000 | 17 MD |
| Total | All source | ~37,000 | 330+ |
3. Backend Module Map
37 Feature Modules (apps/api/src/modules)
Auth & Users:
auth— JWT, login, refresh, password reset, rate limitingusers— User CRUD, account settings (locale, country, dateFormat)roles— Role definitions, permission bitmasks (15 modules × 4 actions)activity-logs— HTTP request logging, audit trail via middleware
Inventory & Operations:
properties— Property CRUD, timezone/currency assignmentroom-types— Room inventory, base rates per propertyroom-mappings— OTA ↔ local room type mappingsuppliers— Supplier/room-owner managementsupplier-room-allocations— M:N supplier ↔ room allocation
OTA Integration:
ota-accounts— Encrypted credentials (AES-256-GCM)ota-connections— Property ↔ OTA account linksota-adapters— Factory + 4 adapters (Booking, Agoda, Traveloka, Expedia)ota-rate-configs— Per-OTA rate formula configurationota-status— OTA-specific status definitions
Bookings & CRM:
bookings— Booking CRUD, upsertFromOta dedupbooking-status— Configurable status definitionsbooking-status-transition— Status state machine transitionsbooking-hooks— Post-status-change side-effect hooks (notifications, availability recalc)customers— Guest profiles, booking consolidation, link/unlink/merge operations
Availability & Rates:
availability— Calendar-based availability matrix, block/unblock date ranges, multi-room selectionrates— Base rate management per room typerate-rules— Markup/discount/seasonal rule definitionsrate-plans— Rate plan configurations with adjustmentsbulk-rates— Batch rate updates across properties/room types
BPM / Workflow Engine:
process-types— Workflow type definitions (booking, OTA onboarding, etc.)process-instances— Active workflow instances trackingprocess-status— Process status definitionsprocess-transitions— State machine transition rules
Sync Engine:
sync-engine— Polling scheduler, job tracking, OTA polling/availability sync processorssync-jobs— Async job tracking with status
Support & System:
alerts— Overbooking detection & notificationsdashboard— KPI metrics (occupancy, revenue, alerts, sync status)settings— App config (sync intervals, notification toggles)notifications— Email service (Resend API + Mailpit in dev)countries— Reference data for filteringhealth— Liveness probesprisma— Prisma client provider module
Common Patterns (apps/api/src/common)
Guards (applied globally, opt-out via @Public):
JwtAuthGuard— JWT signature & expiry validationPermissionsGuard— Module:action bitmask verificationCountryScopeGuard— Country filter injection from user contextThrottlerGuard— Rate limiting (5/min login, 10/min refresh)
Decorators:
@Public()— Skip JwtAuthGuard@RequirePermission(module, action)— Bitwise permission check@CountryScope()— Inject countryScope from user.country
4. Frontend Route Map
| Route | Layer | Auth | Purpose |
|---|---|---|---|
/login, /forgot-password, /reset-password, /change-password | (auth) | Public | Auth flows |
/dashboard | (dashboard) | Required | KPI overview |
/bookings, /bookings/[id] | (dashboard) | Required | Booking list & detail |
/properties, /properties/[id] | (dashboard) | Required | Property list & detail |
/customers, /customers/[id] | (dashboard) | Required | Guest CRM profiles |
/ota-accounts, /ota-accounts/connect | (dashboard) | Required | OTA account management |
/availability | (dashboard) | Required | Availability calendar & blocking |
/rates | (dashboard) | Required | Rate management (OTA formulas) |
/process-instances | (dashboard) | Required | BPM workflow instances |
/suppliers, /suppliers/[id] | (dashboard) | Required | Supplier management |
/alerts, /sync-jobs, /logs | (dashboard) | Required | Monitoring & audit |
/master-data, /settings, /profile | (dashboard) | Required | Configuration |
Context Provider Chain
AuthProvider → CountryProvider → ReferenceDataProvider → ThemeProvider → I18nProvider → ActivityTrackerProviderKey Components (by directory)
availability/— Availability grid, calendar picker, block-range popover, multi-room drag selectionrates/— Price calendar, OTA formula editor, rate rule managercustomers/— Customer table, detail view, booking history mergebookings/— Booking history timeline, status transition dialogproperties/— Property detail tabs, OTA connections managersettings/— Workflow UI visibility, BPM status editors, SMTP profile configlayout/— Sidebar navigation, topbar, country switcherui/— Reusable primitives (data-table, dialog, tabs, etc.)
5. Database Schema (33 Models)
Auth/Users (6): users, roles, refresh_tokens, password_reset_tokens, countries, activity_logs
Inventory (4): properties, room_types, suppliers, supplier_room_allocations
OTA Integration (4): ota_accounts, ota_connections, ota_room_mappings, sync_jobs
Bookings & CRM (6): bookings, booking_status_def, booking_status_transition, availability, customers, ota_status_def
BPM/Workflow (2): process_types, process_instances
Rates (7): rates, rate_rules, rate_plans, rate_plan_adjustments, ota_formula_templates, ota_rate_configs, ota_rate_lines
Operations (4): alerts, audit_logs, settings, property_formula_configs
Key Relationships:
- Property → [RoomTypes, OtaConnections, Availability]
- OtaAccount → OtaConnections → Bookings
- RoomType → [Rates, RateRules, OtaRateConfigs, SupplierRoomAllocations]
- Booking → BookingStatusTransition (state machine)
- ProcessType → ProcessInstances (workflow tracking)
- OtaFormulaTemplate → OtaRateConfig → OtaRateLines (rate formulas)
6. Tech Stack
| Layer | Stack |
|---|---|
| Frontend | Next.js 16, React 18, Tailwind CSS, TanStack Table, SWR, react-hook-form, zod |
| Backend | NestJS 10, Passport JWT, class-validator, BullMQ, Redis |
| Database | PostgreSQL 16, Prisma 7 ORM |
| Auth | JWT + refresh tokens, HttpOnly cookies, bcrypt |
| Encryption | AES-256-GCM (OTA credentials) |
| Build | Turborepo, pnpm workspaces, TypeScript 5.7 |
| Testing | Jest, @nestjs/testing |
7. Key Design Patterns
Authentication: JWT payload (sub, email, roleId, permissions, country, locale) extracted from HttpOnly access_token cookie with Bearer fallback.
Authorization: Bitmask permissions per module (VIEW=1, CREATE=2, EDIT=4, DELETE=8), 6 role presets (super_admin, admin, manager, ota, cs, fin).
OTA Adapters: Factory pattern returning strategy-based adapters for Booking, Agoda, Traveloka, Expedia.
Sync Pipeline: BullMQ repeating jobs (150s) → BookingPull → AvailabilityCalc → OTA push, with SyncJob tracking for audit/retry.
Rate Engine: OTA-formula-based rate calculation. OtaFormulaTemplates define per-OTA price derivation logic. OtaRateConfigs link templates to properties. OtaRateLines store computed daily rates.
BPM Engine: ProcessType definitions drive configurable workflows for booking lifecycle, OTA onboarding, etc. ProcessInstances track active workflow state.
Data Fetching: SWR for frontend caching, Context providers for global state, TanStack Table for CRUD tables.
8. Critical Files
| File | Purpose |
|---|---|
packages/database/prisma/schema.prisma | Source of truth for DB schema |
packages/types/src/enums.ts | OTA types, role enums, status constants |
docs/API_SPEC.md | Backend endpoint contracts |
docs/DB_DESIGN.md | Database design rationale & ER |
docs/BPM_SPEC.md | Business process management spec |
9. Sync Engine Flow (Core Feature)
PollingScheduler (startup) → Creates BullMQ repeating jobs every 150s
↓
OtaPollingProcessor (concurrency: 3) → BookingPullService.pullBookings()
↓
OTA Adapters (factory) → fetchBookings() from each OTA
↓
BookingsService.upsertFromOta() → Dedup & upsert bookings
↓
BookingHooks → Post-upsert side effects (notifications, status checks)
↓
AvailabilitySyncProcessor (concurrency: 2) → AvailabilityCalcService.recalculate()
↓
Count bookings per date, detect isOverbooked
↓
AlertsService (if overbooking) + OTA Adapters.pushAvailability() (always)Last Updated: 2026-03-15 | Status: Active