Order Management System (OMS)
The central nervous system for all commercial transactions. The Order is the Single Source of Truth, replacing the legacy PNR-centric architecture with a true e-commerce model.
Core Philosophy
Order-Centric Architecture
In the modern model, a flight booking is an e-commerce transaction. The Order replaces the fragmented legacy approach where data was scattered across PNR, E-Ticket, and EMD records.
┌─────────────────────────────────────────────────────────────────┐
│ Legacy "Black Box" │ Modern "Glass Box" │
├─────────────────────────────────────────────────────────────────┤
│ │ │
│ ┌─────────┐ │ ┌─────────────────┐ │
│ │ PNR │◄──┐ │ │ │ │
│ └─────────┘ │ │ │ Universal │ │
│ ┌─────────┐ │ Fragmented │ │ Order ID │ │
│ │ E-Ticket│◄──┼── Data │ │ (UUID) │ │
│ └─────────┘ │ │ │ │ │
│ ┌─────────┐ │ │ │ ┌───────────┐ │ │
│ │ EMD │◄──┘ │ │ │Flight SKU │ │ │
│ └─────────┘ │ │ │Seat SKU │ │ │
│ │ │ │Bag SKU │ │ │
│ GDS_CODE:XF39 │ │ │Meal SKU │ │ │
│ TICKET_STOCK_REF_34 │ │ └───────────┘ │ │
│ IATA_RES_MSG │ │ │ │
│ RAW_DATA_BLOCK │ └─────────────────┘ │
│ │ │
└─────────────────────────────────────────────────────────────────┘
Treating a Seat Like a SKU
Every product in the airline's portfolio is a line item in the Order:
| Product Type | SKU Example | Description |
|---|---|---|
| Flight Segment | FLT-CCS-MAR-20250315-0800 | Base transportation |
| Seat Selection | SEAT-12A-WINDOW | Specific seat assignment |
| Baggage | BAG-20KG-CHECKED | Checked baggage allowance |
| Meal | MEAL-VGML | Special meal selection |
| Priority Boarding | SVC-PRIORITY-BOARD | Service add-on |
| Lounge Access | SVC-LOUNGE-CCS | Airport service |
Universal Order ID
- Format: UUID v7 (time-ordered for indexing efficiency)
- Example:
018e4a3c-7b2a-7d4e-8f5a-1b2c3d4e5f6a - Replaces: PNR as primary identifier
- PNR Retained: As secondary identifier for backward compatibility
Order State Machine
The Order lifecycle follows a strict state machine that governs all downstream operations:
┌─────────────────────────────────────────────┐
│ │
│ OFFERED ──────────────► PAID │
│ │ │ │
│ │ (timeout/ │ (payment │
│ │ abandon) │ received) │
│ ▼ │ │
│ EXPIRED │ │
│ │ │
│ ▼ │
│ PAID ◄────────┐ │
│ │ │ │
│ ┌─────────────┼───────────┘ │
│ │ │ (service │
│ │ (refund/ │ delivery) │
│ │ cancel) │ │
│ ▼ ▼ │
│ CANCELLED FULFILLED │
│ │ │
│ │ (post-flight) │
│ ▼ │
│ COMPLETED │
│ │
└─────────────────────────────────────────────┘
State Definitions
| State | Description | Allowed Actions |
|---|---|---|
OFFERED | Shopping cart, price quoted | Add/remove items, abandon, pay |
EXPIRED | Offer timed out (10 min) | Restart shopping |
PAID | Payment received, confirmed | Check-in, modify, cancel |
CANCELLED | Order cancelled, refunded | None |
FULFILLED | Services delivered (flight taken) | Post-service claims |
COMPLETED | Final state, all settled | Archived |
Critical Business Rule
┌─────────────────────────────────────────────────────────────────┐
│ │
│ CRITICAL LOGIC: Check-in PROHIBITED unless State == PAID │
│ │
│ This prevents revenue leakage by ensuring no passenger │
│ boards without confirmed payment. │
│ │
└─────────────────────────────────────────────────────────────────┘
Implementation:
IF Order.Status == 'PAID' {
ALLOW check-in
GENERATE boarding pass
} ELSE {
RETURN Error('Payment Required')
BLOCK check-in
}
Data Model
Order Schema
Order
├── OrderID (UUID v7) ────────────── Primary identifier
├── RecordLocator (6-char) ───────── Legacy PNR reference
├── Status ───────────────────────── State machine value
├── CreatedAt, UpdatedAt
├── ExpiresAt ────────────────────── For OFFERED state (10 min)
│
├── Customer
│ ├── CustomerID (UUID)
│ ├── Email, Phone
│ └── LoyaltyID (optional)
│
├── Passengers[]
│ ├── PassengerID (UUID)
│ ├── Name (Surname/Given)
│ ├── Type (ADT/CHD/INF)
│ ├── DateOfBirth
│ ├── Documents[]
│ │ ├── Type (PP/ID/VISA)
│ │ ├── Number, Issuing Country
│ │ └── Expiry
│ └── Contact (email, phone)
│
├── Items[] ──────────────────────── Line items (SKUs)
│ ├── ItemID (UUID)
│ ├── SKU
│ ├── Type (FLIGHT/SEAT/BAGGAGE/SERVICE)
│ ├── Description
│ ├── PassengerRef ─────────────── Links to passenger
│ ├── SegmentRef ───────────────── Links to segment (if applicable)
│ ├── Pricing
│ │ ├── BaseAmount
│ │ ├── Taxes[]
│ │ └── TotalAmount
│ └── Status (OFFERED/CONFIRMED/DELIVERED/CANCELLED)
│
├── Segments[]
│ ├── SegmentID (UUID)
│ ├── FlightNumber, Date
│ ├── Origin, Destination
│ ├── DepartureTime, ArrivalTime
│ ├── PriceTier (P1-P5) ────────── Numerical pricing tier
│ ├── CabinClass
│ └── Status
│
├── Payments[]
│ ├── PaymentID (UUID)
│ ├── TokenRef ─────────────────── Payment gateway token
│ ├── Amount, Currency
│ ├── Method (CARD/WALLET/BNPL)
│ ├── Status (AUTHORIZED/CAPTURED/REFUNDED)
│ └── GatewayResponse
│
└── History[] ────────────────────── Audit trail
├── Timestamp
├── Action
├── PreviousState
├── NewState
└── Actor (customer/agent/system)
Prisma Schema Example
model Order {
id String @id @default(uuid()) @db.Uuid
recordLocator String @unique @db.VarChar(6)
status OrderStatus @default(OFFERED)
customerId String @db.Uuid
customer Customer @relation(fields: [customerId], references: [id])
passengers Passenger[]
items OrderItem[]
segments Segment[]
payments Payment[]
history OrderHistory[]
expiresAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([recordLocator])
@@index([customerId])
@@index([status])
}
enum OrderStatus {
OFFERED
EXPIRED
PAID
CANCELLED
FULFILLED
COMPLETED
}
model OrderItem {
id String @id @default(uuid()) @db.Uuid
orderId String @db.Uuid
order Order @relation(fields: [orderId], references: [id])
sku String
itemType ItemType
description String
passengerId String? @db.Uuid
passenger Passenger? @relation(fields: [passengerId], references: [id])
segmentId String? @db.Uuid
segment Segment? @relation(fields: [segmentId], references: [id])
baseAmount Decimal @db.Decimal(10, 2)
taxAmount Decimal @db.Decimal(10, 2)
totalAmount Decimal @db.Decimal(10, 2)
currency String @db.VarChar(3)
status ItemStatus @default(OFFERED)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum ItemType {
FLIGHT
SEAT
BAGGAGE
MEAL
SERVICE
}
enum ItemStatus {
OFFERED
CONFIRMED
DELIVERED
CANCELLED
}
Integration Points
The OMS is the central hub that all other systems query:
┌─────────────┐
│ │
┌─────────────────► OMS ◄─────────────────┐
│ │ │ │
│ └──────┬──────┘ │
│ │ │
┌───────┴───────┐ ┌───────────┼───────────┐ ┌──────┴──────┐
│ │ │ │ │ │ │
│ Inventory │ │ ┌──────▼──────┐ │ │ Payment │
│ (P1-P5) │ │ │ │ │ │ Vault │
│ │ │ │ DCS │ │ │ │
└───────────────┘ │ │ (View) │ │ └─────────────┘
│ │ │ │
┌───────────────┐ │ └─────────────┘ │ ┌─────────────┐
│ │ │ │ │ │
│ Offer Engine │ │ ┌─────────────┐ │ │ Load │
│ (NDC) │ │ │ │ │ │ Control │
│ │ │ │ Ticketing │ │ │ │
└───────────────┘ │ │ │ │ └─────────────┘
│ └─────────────┘ │
│ │
└───────────────────────┘
System Integration
| System | Direction | Data | Pattern |
|---|---|---|---|
| Inventory | Bidirectional | Availability, holds | Sync (sub-ms) |
| Offer Engine | Outbound | Order items for pricing | Request/Response |
| DCS | Outbound | Order status, passenger data | Real-time query |
| Payment Vault | Bidirectional | Payment tokens | Event-driven |
| Ticketing | Outbound | Confirmed orders | Event-driven |
| Load Control | Outbound | Passenger count, bag weights | Real-time query |
| Notifications | Outbound | Order events | Event-driven |
| Analytics | Outbound | Order data | Streaming |
Research Topics
- UUID v7 implementation for time-ordered identifiers
- Saga pattern for distributed order transactions
- Event sourcing for order history
- CQRS for read/write optimization
- Order expiration and cleanup strategies
- Multi-currency order handling
- Order splitting/merging scenarios
- Group order management
Transition from Legacy PNR
Migration Strategy
- Dual-Write Phase: New orders written to OMS, legacy PNR created for compatibility
- Shadow Mode: OMS becomes primary, PNR synced for legacy systems
- Deprecation: PNR generation disabled, read-only access for history
- Archive: Legacy PNR data migrated to order history
Backward Compatibility
- PNR (RecordLocator) retained as secondary identifier
- Legacy systems can query by PNR, resolved to OrderID
- GDS connectivity (if needed) maps PNR to Order
- Reporting maintains PNR for historical analysis