Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbc6ffe77a | ||
|
|
bf3f987dce | ||
|
|
cf458536fb | ||
|
|
287bbb2acd | ||
|
|
2dc4faa410 | ||
|
|
5d83099957 | ||
|
|
61d5edb7a2 | ||
|
|
b8510d9902 | ||
|
|
aaa08ee57f | ||
|
|
6c1a80587e | ||
|
|
5780b5cd47 | ||
|
|
1d96290618 | ||
|
|
b83ec24268 | ||
|
|
0a06a3856f | ||
|
|
46770d4b2b | ||
|
|
e7a9ee911e | ||
|
|
4ee9e36e2b | ||
|
|
5779501812 | ||
|
|
fd54fc6a0e | ||
|
|
8d11cf85ea | ||
|
|
9d386580c8 | ||
|
|
67756b88bd | ||
|
|
5e4e37c948 | ||
|
|
dfce163ca0 | ||
|
|
e9f5fd2e7b | ||
|
|
1f8c29d850 | ||
|
|
689be81442 | ||
|
|
ad90a5b082 | ||
|
|
7f529d8ae4 | ||
|
|
5f95a5c341 | ||
|
|
06a1ee518e | ||
|
|
e920c9e3b5 | ||
|
|
dbfce10983 | ||
|
|
a7733ad28f | ||
|
|
98df6f18b4 | ||
|
|
345d04407a | ||
|
|
e3edd7a6c4 | ||
|
|
ee7796e6d3 | ||
|
|
0d8a6228f4 | ||
|
|
03990c71fe | ||
|
|
7413167f79 | ||
|
|
2c0cad7093 | ||
|
|
86f435500a | ||
|
|
a8c8b11ba5 | ||
|
|
9f3b3ad4fd | ||
|
|
7afd58c178 | ||
|
|
1fe403cb11 | ||
|
|
e209541475 | ||
|
|
046d36d069 | ||
|
|
393963a982 | ||
|
|
5cd42c914f | ||
|
|
c90c96b8e5 | ||
|
|
9cf49bc05e | ||
|
|
894660b865 | ||
|
|
1d4b160660 | ||
|
|
a5770d1e0f | ||
|
|
2cdd921012 | ||
|
|
bef7aa98c1 | ||
|
|
dfd2ff8127 | ||
|
|
e8e6da31be | ||
|
|
de7527e1bd | ||
|
|
f3acfd2181 | ||
|
|
4fd1058dfe | ||
|
|
c5b360bf56 | ||
|
|
4ba1316289 | ||
|
|
fd196f559b | ||
|
|
13fa6c2d46 | ||
|
|
7473456317 | ||
|
|
49b5fcb487 | ||
|
|
3137cb8038 | ||
|
|
6e7ff937dc | ||
|
|
e99f292e24 | ||
|
|
18454d5197 | ||
|
|
4441fa2cce | ||
|
|
c3936ca692 | ||
|
|
1d0c41bf8c | ||
|
|
28837230fa | ||
|
|
1e3ec441dc | ||
|
|
06598ea462 | ||
|
|
44afa45f7a | ||
|
|
9e64243759 | ||
|
|
8021937518 | ||
|
|
25302cc222 | ||
|
|
46e4a0ed81 | ||
|
|
82ea313f34 | ||
|
|
025f114828 |
@@ -0,0 +1,10 @@
|
|||||||
|
DB_HOST=106.51.105.22
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=ar_dev
|
||||||
|
DB_USER=ar_user
|
||||||
|
DB_PASSWORD="V$:Q1Hc6Qh]@#Fr"
|
||||||
|
DB_SYNCHRONIZE=true
|
||||||
|
DB_SSL=false
|
||||||
|
PORT=9501
|
||||||
|
CORS_ORIGIN=https://ardev.maskantech.in
|
||||||
|
NODE_ENV=dev
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
PORT=3001
|
|
||||||
DATABASE_URL=postgresql://username:password@localhost:5432/dbname
|
|
||||||
REDIS_URL=redis://localhost:6379
|
|
||||||
KAFKA_BROKERS=localhost:9092
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
DB_HOST=106.51.105.22
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=ar_test
|
||||||
|
DB_USER=ar_user
|
||||||
|
DB_PASSWORD="V$:Q1Hc6Qh]@#Fr"
|
||||||
|
DB_SYNCHRONIZE=true
|
||||||
|
DB_SSL=false
|
||||||
|
PORT=9502
|
||||||
|
CORS_ORIGIN=https://artest.maskantech.in
|
||||||
|
NODE_ENV=test
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
DB_HOST=106.51.105.22
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=ar_uat
|
||||||
|
DB_USER=ar_user
|
||||||
|
DB_PASSWORD="V$:Q1Hc6Qh]@#Fr"
|
||||||
|
DB_SYNCHRONIZE=true
|
||||||
|
DB_SSL=false
|
||||||
|
PORT=9501
|
||||||
|
CORS_ORIGIN=https://aruat.maskantech.in
|
||||||
|
NODE_ENV=uat
|
||||||
+5
-3
@@ -34,8 +34,10 @@ lerna-debug.log*
|
|||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
|
||||||
|
# Local agent customization
|
||||||
|
.agent.md
|
||||||
|
|
||||||
# Environment variables
|
# Environment variables
|
||||||
.env
|
|
||||||
.env.test
|
|
||||||
.env.production
|
|
||||||
.env.local
|
.env.local
|
||||||
|
.env
|
||||||
|
|||||||
@@ -1,30 +1,125 @@
|
|||||||
# Aero Resolve - Backend
|
# AeroResolve Backend
|
||||||
|
|
||||||
This is the backend REST API powered by NestJS.
|
test1
|
||||||
|
NestJS REST API for AeroResolve.
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## Current Modules
|
||||||
|
|
||||||
### Prerequisites
|
| Module | Status | Description |
|
||||||
- Node.js (v18+)
|
| ------------- | ----------- | ---------------------------------------- |
|
||||||
|
| `health` | Implemented | Health check |
|
||||||
|
| `database` | Implemented | PostgreSQL / TypeORM setup |
|
||||||
|
| `master-data` | Implemented | CRUD and seed data for lookup categories |
|
||||||
|
| `cohort` | Implemented | Cohort CRUD, pagination, status update |
|
||||||
|
|
||||||
### Installation
|
## Prerequisites
|
||||||
1. Navigate to the backend directory (if you aren't already here):
|
|
||||||
```bash
|
- Node.js 18+
|
||||||
cd backend
|
- npm
|
||||||
```
|
- PostgreSQL
|
||||||
2. Install the dependencies using npm:
|
|
||||||
```bash
|
## Install
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Development
|
|
||||||
Start the local development server in watch mode:
|
|
||||||
```bash
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Files
|
||||||
|
|
||||||
|
The app loads environment files based on `NODE_ENV`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.env.local
|
||||||
|
.env.dev
|
||||||
|
.env.test
|
||||||
|
.env.uat
|
||||||
|
```
|
||||||
|
|
||||||
|
Required values:
|
||||||
|
|
||||||
|
```text
|
||||||
|
PORT=3001
|
||||||
|
CORS_ORIGIN=http://localhost:5174
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_USER=<postgres-user>
|
||||||
|
DB_PASSWORD=<postgres-password>
|
||||||
|
DB_NAME=<database-name>
|
||||||
|
DB_SYNCHRONIZE=true
|
||||||
|
DB_SSL=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Local
|
||||||
|
npm run local
|
||||||
|
npm run start:local
|
||||||
|
|
||||||
|
# Dev
|
||||||
npm run dev
|
npm run dev
|
||||||
|
npm run start:dev
|
||||||
|
|
||||||
|
# UAT
|
||||||
|
npm run uat
|
||||||
|
npm run start:uat
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build for Production
|
## API
|
||||||
To compile the NestJS application:
|
|
||||||
```bash
|
Base URL:
|
||||||
npm run build
|
|
||||||
|
```text
|
||||||
|
http://localhost:3001/api
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Swagger:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:3001/docs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
| Method | Path |
|
||||||
|
| -------- | -------------------------------- |
|
||||||
|
| `GET` | `/api/health` |
|
||||||
|
| `GET` | `/api/master-data/:category` |
|
||||||
|
| `POST` | `/api/master-data/:category` |
|
||||||
|
| `GET` | `/api/master-data/:category/:id` |
|
||||||
|
| `PUT` | `/api/master-data/:category/:id` |
|
||||||
|
| `DELETE` | `/api/master-data/:category/:id` |
|
||||||
|
| `GET` | `/api/cohorts?page=1&limit=10` |
|
||||||
|
| `POST` | `/api/cohorts` |
|
||||||
|
| `GET` | `/api/cohorts/:id` |
|
||||||
|
| `PUT` | `/api/cohorts/:id` |
|
||||||
|
| `PATCH` | `/api/cohorts/:id/status` |
|
||||||
|
| `DELETE` | `/api/cohorts/:id` |
|
||||||
|
|
||||||
|
## Seed Master Data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run seed:local
|
||||||
|
npm run seed:dev
|
||||||
|
npm run seed:test
|
||||||
|
npm run seed:uat
|
||||||
|
```
|
||||||
|
|
||||||
|
Seeded categories:
|
||||||
|
|
||||||
|
- `MEMBERSHIP_TIER`
|
||||||
|
- `CUSTOMER_VALUE`
|
||||||
|
- `REGION`
|
||||||
|
- `TRIP_PURPOSE`
|
||||||
|
- `CABIN_CLASS`
|
||||||
|
- `PASSENGER_TYPE`
|
||||||
|
- `ANCILLARY_PURCHASE`
|
||||||
|
- `REVENUE_SEGMENT`
|
||||||
|
|
||||||
|
## Planned Next
|
||||||
|
|
||||||
|
- Tenant foundation
|
||||||
|
- Auth / RBAC
|
||||||
|
- Audit logging
|
||||||
|
- Policy / regulation engine backend
|
||||||
|
- Compensation engine
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "HOTEL_ACCOMMODATION",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "hotel_tier",
|
||||||
|
"fieldName": "Hotel Tier",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "hotel-tier",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Hotel Details",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "room_type",
|
||||||
|
"fieldName": "Room Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "room-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Hotel Details",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "number_of_rooms",
|
||||||
|
"fieldName": "Number of Rooms",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Hotel Details",
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "number_of_nights",
|
||||||
|
"fieldName": "Number of Nights",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Hotel Details",
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "meal_included",
|
||||||
|
"fieldName": "Meal Included",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "meal-type",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Hotel Details",
|
||||||
|
"displayOrder": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "check_in_date",
|
||||||
|
"fieldName": "Check-in Date",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Schedule",
|
||||||
|
"displayOrder": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "check_out_date",
|
||||||
|
"fieldName": "Check-out Date",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Schedule",
|
||||||
|
"displayOrder": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "preferred_hotel_chain",
|
||||||
|
"fieldName": "Preferred Hotel Chain",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "hotel-chain",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Preferences",
|
||||||
|
"displayOrder": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_budget",
|
||||||
|
"fieldName": "Maximum Budget",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Preferences",
|
||||||
|
"displayOrder": 9,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Preferences",
|
||||||
|
"displayOrder": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "AIRPORT_HOTEL",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "hotel_category",
|
||||||
|
"fieldName": "Hotel Category",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "hotel-category",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "duration_hours",
|
||||||
|
"fieldName": "Duration (Hours)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_budget",
|
||||||
|
"fieldName": "Maximum Budget",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 3,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "REGULATORY_COMPENSATION",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "compensation_rule",
|
||||||
|
"fieldName": "Compensation Rule",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "compensation-rule",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Compensation Rules",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Compensation Rules",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "compensation_amount",
|
||||||
|
"fieldName": "Compensation Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 3,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "payment_method",
|
||||||
|
"fieldName": "Payment Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "payment_due_within_days",
|
||||||
|
"fieldName": "Payment Due Within (Days)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Approval",
|
||||||
|
"displayOrder": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "AIRLINE_GOODWILL_CASH",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "goodwill_amount",
|
||||||
|
"fieldName": "Goodwill Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Goodwill Details",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "reason_code",
|
||||||
|
"fieldName": "Reason Code",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "goodwill-reason",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Goodwill Details",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "EX_GRATIA_COMPENSATION",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "amount",
|
||||||
|
"fieldName": "Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_level",
|
||||||
|
"fieldName": "Approval Level",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "approval-level",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Approval",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "AWARD_MILES",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "miles_to_credit",
|
||||||
|
"fieldName": "Miles to Credit",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "expiry_date",
|
||||||
|
"fieldName": "Expiry",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "loyalty_program",
|
||||||
|
"fieldName": "Loyalty Program",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "loyalty-program",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "BONUS_MILES",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "bonus_miles",
|
||||||
|
"fieldName": "Bonus Miles",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "promotion_code",
|
||||||
|
"fieldName": "Promotion Code",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "promotion-code",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TIER_POINTS",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "tier_points",
|
||||||
|
"fieldName": "Tier Points",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "validity_date",
|
||||||
|
"fieldName": "Validity",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TIER_UPGRADE",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "target_tier",
|
||||||
|
"fieldName": "Target Tier",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "membership-tier",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "upgrade_duration_months",
|
||||||
|
"fieldName": "Upgrade Duration (Months)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Loyalty",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "MEAL_VOUCHER",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "voucher_amount",
|
||||||
|
"fieldName": "Voucher Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "meal_type",
|
||||||
|
"fieldName": "Meal Type",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "meal-type",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "validity_hours",
|
||||||
|
"fieldName": "Validity (Hours)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Restrictions",
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "airport_restriction",
|
||||||
|
"fieldName": "Airport Restriction",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "airport-restriction",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Restrictions",
|
||||||
|
"displayOrder": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "RESTAURANT_VOUCHER",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "partner_restaurant",
|
||||||
|
"fieldName": "Partner Restaurant",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "voucher_value",
|
||||||
|
"fieldName": "Voucher Value",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 2,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "expiry_date",
|
||||||
|
"fieldName": "Expiry",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Restrictions",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "REFRESHMENT_COUPON",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "coupon_amount",
|
||||||
|
"fieldName": "Coupon Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "General Information",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,311 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "FULL_TICKET_REFUND",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_basis",
|
||||||
|
"fieldName": "Refund Basis",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-basis",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_amount",
|
||||||
|
"fieldName": "Refund Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 3,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_refund_limit",
|
||||||
|
"fieldName": "Maximum Refund Limit",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 4,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_method",
|
||||||
|
"fieldName": "Refund Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Finance / Payment Gateway",
|
||||||
|
"displayOrder": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "PARTIAL_TICKET_REFUND",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_component",
|
||||||
|
"fieldName": "Refund Component",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "refund-component",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_percentage",
|
||||||
|
"fieldName": "Refund Percentage",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_amount",
|
||||||
|
"fieldName": "Refund Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 4,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_refund_limit",
|
||||||
|
"fieldName": "Maximum Refund Limit",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 5,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_method",
|
||||||
|
"fieldName": "Refund Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Finance",
|
||||||
|
"displayOrder": 7
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TAX_REFUND",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "tax_type",
|
||||||
|
"fieldName": "Tax Type",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "tax-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Amount Type",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_amount",
|
||||||
|
"fieldName": "Refund Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 3,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_method",
|
||||||
|
"fieldName": "Refund Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Method",
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Approval Required",
|
||||||
|
"displayOrder": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "ANCILLARY_REFUND",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "ancillary_type",
|
||||||
|
"fieldName": "Ancillary Type",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "ancillary-purchase",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Amount Type",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_amount",
|
||||||
|
"fieldName": "Refund Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 3,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_method",
|
||||||
|
"fieldName": "Refund Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Method",
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Approval Required",
|
||||||
|
"displayOrder": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "BAGGAGE_FEE_REFUND",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "baggage_type",
|
||||||
|
"fieldName": "Baggage Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "baggage-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Basis",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_basis",
|
||||||
|
"fieldName": "Refund Basis",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-basis",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Basis",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "amount_type",
|
||||||
|
"fieldName": "Amount Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "amount-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_amount",
|
||||||
|
"fieldName": "Refund Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Amount",
|
||||||
|
"displayOrder": 4,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "refund_method",
|
||||||
|
"fieldName": "Refund Method",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "refund-method",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Refund Method",
|
||||||
|
"displayOrder": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "approval_required",
|
||||||
|
"fieldName": "Approval Required",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Approval Required",
|
||||||
|
"displayOrder": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TAXI",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_fare",
|
||||||
|
"fieldName": "Maximum Fare",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "pickup_radius_km",
|
||||||
|
"fieldName": "Pickup Radius (Kilometers)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "destination_type",
|
||||||
|
"fieldName": "Destination Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "destination-type",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "AIRPORT_TRANSFER",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "vehicle_type",
|
||||||
|
"fieldName": "Vehicle Type",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "vehicle-category",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_distance_km",
|
||||||
|
"fieldName": "Maximum Distance (Kilometers)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "BUS_TRANSFER",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "route",
|
||||||
|
"fieldName": "Route",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "route",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "number_of_passengers",
|
||||||
|
"fieldName": "Number of Passengers",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Ground Transport",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TRAIN_TICKET",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "ticket_class",
|
||||||
|
"fieldName": "Ticket Class",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "cabin-class",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Partner API",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_fare",
|
||||||
|
"fieldName": "Maximum Fare",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Partner API",
|
||||||
|
"displayOrder": 2,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "CHAUFFEUR_SERVICE",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "vehicle_category",
|
||||||
|
"fieldName": "Vehicle Category",
|
||||||
|
"fieldType": "dropdown",
|
||||||
|
"lookupSource": "vehicle-category",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Partner API",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "service_radius_km",
|
||||||
|
"fieldName": "Service Radius (Kilometers)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Partner API",
|
||||||
|
"displayOrder": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"actionTypeCode": "TRAVEL_VOUCHER",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "voucher_value",
|
||||||
|
"fieldName": "Voucher Value",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Voucher Details",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "validity_months",
|
||||||
|
"fieldName": "Validity (Months)",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Voucher Rules",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "transferable",
|
||||||
|
"fieldName": "Transferable",
|
||||||
|
"fieldType": "switch",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Voucher Rules",
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "applicable_routes",
|
||||||
|
"fieldName": "Applicable Routes",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "flight-type",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Voucher Rules",
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "fare_classes",
|
||||||
|
"fieldName": "Fare Classes",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "cabin-class",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Voucher Rules",
|
||||||
|
"displayOrder": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "FUTURE_TRAVEL_CREDIT",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "credit_amount",
|
||||||
|
"fieldName": "Credit Amount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Credit Details",
|
||||||
|
"displayOrder": 1,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "expiry_date",
|
||||||
|
"fieldName": "Expiry Date",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Credit Rules",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "eligible_fare_types",
|
||||||
|
"fieldName": "Eligible Fare Types",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "eligible-fare-type",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Credit Rules",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "PROMO_CODE",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "code_value",
|
||||||
|
"fieldName": "Code Value",
|
||||||
|
"fieldType": "text",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Promo Details",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "validity_date",
|
||||||
|
"fieldName": "Validity",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Promo Rules",
|
||||||
|
"displayOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "applicable_products",
|
||||||
|
"fieldName": "Applicable Products",
|
||||||
|
"fieldType": "multi_select",
|
||||||
|
"lookupSource": "applicable-product",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "full",
|
||||||
|
"section": "Promo Rules",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionTypeCode": "DISCOUNT_COUPON",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldCode": "discount_percentage",
|
||||||
|
"fieldName": "Discount Percentage",
|
||||||
|
"fieldType": "number",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Discount Details",
|
||||||
|
"displayOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "maximum_discount",
|
||||||
|
"fieldName": "Maximum Discount",
|
||||||
|
"fieldType": "currency",
|
||||||
|
"isRequired": false,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Discount Details",
|
||||||
|
"displayOrder": 2,
|
||||||
|
"lookupSource": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldCode": "expiry_date",
|
||||||
|
"fieldName": "Expiry",
|
||||||
|
"fieldType": "date",
|
||||||
|
"isRequired": true,
|
||||||
|
"width": "half",
|
||||||
|
"section": "Discount Rules",
|
||||||
|
"displayOrder": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,647 @@
|
|||||||
|
-- =============================================================================
|
||||||
|
-- AeroResolve Database Schema
|
||||||
|
-- PostgreSQL 14+
|
||||||
|
-- Generated from TypeORM entities (aeroresolve_backend)
|
||||||
|
-- =============================================================================
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||||
|
|
||||||
|
-- ─── Schemas ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE SCHEMA IF NOT EXISTS tenant;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_rule_engine;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_action_builder;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_lookup;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS cohort;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS policy_engine;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS audit;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS recovery_incident;
|
||||||
|
|
||||||
|
-- ─── Audit Logs ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS audit.tbl_audit_logs (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
tenant_id VARCHAR(255) NOT NULL,
|
||||||
|
module VARCHAR(100) NOT NULL,
|
||||||
|
action VARCHAR(50) NOT NULL,
|
||||||
|
entity_id VARCHAR(255),
|
||||||
|
entity_label VARCHAR(255),
|
||||||
|
before JSONB,
|
||||||
|
after JSONB,
|
||||||
|
performed_by VARCHAR(255),
|
||||||
|
ip_address VARCHAR(50),
|
||||||
|
user_agent TEXT,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_tenant ON audit.tbl_audit_logs (tenant_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_module ON audit.tbl_audit_logs (module);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_action ON audit.tbl_audit_logs (action);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_entity ON audit.tbl_audit_logs (entity_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_audit_createdat ON audit.tbl_audit_logs (created_at DESC);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ─── Enum Types ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE cohort.cohort_high_value_passenger_enum AS ENUM (
|
||||||
|
'Any',
|
||||||
|
'Yes(VIP/Strategic)',
|
||||||
|
'No'
|
||||||
|
);
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN NULL;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE cohort.cohort_flight_type_enum AS ENUM (
|
||||||
|
'Domestic Only',
|
||||||
|
'International Only',
|
||||||
|
'Both (All)'
|
||||||
|
);
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN NULL;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- ─── Tenants ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tenant.tbl_tenants (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
slug VARCHAR NOT NULL,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
tier VARCHAR NOT NULL DEFAULT 'standard',
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT uq_tbl_tenants_slug UNIQUE (slug)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ─── 1. Masters Lookup Schema (Domain Master Tables) ─────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_membership_tiers (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_customer_values (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_regions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_trip_purposes (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_cabin_classes (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_passenger_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_ancillary_purchases (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_revenue_segments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_jurisdictions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_booking_channels (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_flight_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_journey_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_fare_flexibilities (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_carrier_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_special_assistance_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_delay_reasons (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_delay_durations (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_extraordinary_circumstances (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_cancellation_reasons (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_diversion_reasons (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_missed_connection_reasons (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_compensation_eligibilities (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_compensation_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_refund_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_flight_disruption_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_airline_responsibilities (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_weather_conditions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_atc_restrictions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_technical_fault_categories (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_refund_bases (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_currencies (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
symbol VARCHAR,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_refund_methods (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_amount_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
label VARCHAR NOT NULL,
|
||||||
|
value VARCHAR NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ─── 2. Masters Rule Engine Schema (Condition & Category Metadata) ───────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_rule_engine.tbl_rules_categories (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
code VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
name VARCHAR(150) NOT NULL,
|
||||||
|
"tableName" VARCHAR,
|
||||||
|
description TEXT,
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_rule_engine.tbl_condition_groups (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
code VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
name VARCHAR(150) NOT NULL,
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_rule_engine.tbl_rule_category_groups (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"ruleCategoryId" UUID NOT NULL REFERENCES masters_rule_engine.tbl_rules_categories(id) ON DELETE CASCADE,
|
||||||
|
"conditionGroupId" UUID NOT NULL REFERENCES masters_rule_engine.tbl_condition_groups(id) ON DELETE CASCADE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT uq_rule_category_group UNIQUE ("ruleCategoryId", "conditionGroupId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_rule_engine.tbl_condition_fields (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"groupId" UUID NOT NULL REFERENCES masters_rule_engine.tbl_condition_groups(id) ON DELETE CASCADE,
|
||||||
|
code VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
name VARCHAR(150) NOT NULL,
|
||||||
|
"lookupTable" VARCHAR,
|
||||||
|
"dataType" VARCHAR NOT NULL DEFAULT 'STRING',
|
||||||
|
"operatorType" VARCHAR NOT NULL DEFAULT 'COMPARISON',
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_rule_engine.tbl_operators (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
code VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
symbol VARCHAR(20),
|
||||||
|
"dataTypes" TEXT[],
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ─── 3. Masters Action Builder Schema ───────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_action_builder.tbl_action_categories (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
code VARCHAR NOT NULL UNIQUE,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_action_builder.tbl_action_types (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"categoryId" UUID NOT NULL REFERENCES masters_action_builder.tbl_action_categories(id) ON DELETE CASCADE,
|
||||||
|
code VARCHAR NOT NULL UNIQUE,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
"displayOrder" INT DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN DEFAULT TRUE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_action_builder.tbl_field_definitions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"actionTypeId" UUID NOT NULL REFERENCES masters_action_builder.tbl_action_types(id) ON DELETE CASCADE,
|
||||||
|
"fieldCode" VARCHAR NOT NULL,
|
||||||
|
"fieldName" VARCHAR NOT NULL,
|
||||||
|
"fieldType" VARCHAR NOT NULL,
|
||||||
|
"lookupSource" VARCHAR,
|
||||||
|
"isRequired" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"defaultValue" TEXT,
|
||||||
|
placeholder VARCHAR,
|
||||||
|
"helpText" TEXT,
|
||||||
|
width VARCHAR NOT NULL DEFAULT 'full',
|
||||||
|
section VARCHAR,
|
||||||
|
"displayOrder" INT NOT NULL DEFAULT 0,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"validationJson" JSONB,
|
||||||
|
"visibilityConditionJson" JSONB,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_field_definition_action_type_code
|
||||||
|
ON masters_action_builder.tbl_field_definitions("actionTypeId", "fieldCode");
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_action_builder.tbl_action_submissions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"categoryId" UUID NOT NULL REFERENCES masters_action_builder.tbl_action_categories(id) ON DELETE CASCADE,
|
||||||
|
"actionTypeId" UUID NOT NULL REFERENCES masters_action_builder.tbl_action_types(id) ON DELETE CASCADE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS masters_action_builder.tbl_action_submission_values (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"submissionId" UUID NOT NULL REFERENCES masters_action_builder.tbl_action_submissions(id) ON DELETE CASCADE,
|
||||||
|
"fieldDefinitionId" UUID REFERENCES masters_action_builder.tbl_field_definitions(id) ON DELETE CASCADE,
|
||||||
|
"fieldCode" VARCHAR,
|
||||||
|
"valueIndex" INT NOT NULL DEFAULT 0,
|
||||||
|
"selectedValueId" VARCHAR,
|
||||||
|
"textValue" TEXT,
|
||||||
|
"numberValue" NUMERIC,
|
||||||
|
"booleanValue" BOOLEAN,
|
||||||
|
"dateValue" DATE,
|
||||||
|
"timeValue" TIME,
|
||||||
|
"timestampValue" TIMESTAMP WITH TIME ZONE,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ─── Cohorts ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohorts (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
|
||||||
|
"scopeType" VARCHAR,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
description VARCHAR,
|
||||||
|
status VARCHAR NOT NULL DEFAULT 'Draft',
|
||||||
|
"highValuePassenger" cohort.cohort_high_value_passenger_enum NOT NULL DEFAULT 'Any',
|
||||||
|
"flightType" cohort.cohort_flight_type_enum,
|
||||||
|
"originAirport" TEXT,
|
||||||
|
"destinationAirport" TEXT,
|
||||||
|
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tbl_cohorts_tenant ON cohort.tbl_cohorts("tenantId");
|
||||||
|
|
||||||
|
-- ─── Cohort Join Tables (Many-to-Many) ──────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_cabin_classes (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"cabinClassId" UUID NOT NULL REFERENCES masters_lookup.tbl_cabin_classes(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "cabinClassId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_passenger_types (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"passengerTypeId" UUID NOT NULL REFERENCES masters_lookup.tbl_passenger_types(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "passengerTypeId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_ancillary_purchases (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"ancillaryPurchaseId" UUID NOT NULL REFERENCES masters_lookup.tbl_ancillary_purchases(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "ancillaryPurchaseId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_loyalty_tiers (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"membershipTierId" UUID NOT NULL REFERENCES masters_lookup.tbl_membership_tiers(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "membershipTierId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_revenue_segments (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"revenueSegmentId" UUID NOT NULL REFERENCES masters_lookup.tbl_revenue_segments(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "revenueSegmentId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_regions (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"regionId" UUID NOT NULL REFERENCES masters_lookup.tbl_regions(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "regionId")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cohort.tbl_cohort_trip_purposes (
|
||||||
|
"cohortId" UUID NOT NULL REFERENCES cohort.tbl_cohorts(id) ON DELETE CASCADE,
|
||||||
|
"tripPurposeId" UUID NOT NULL REFERENCES masters_lookup.tbl_trip_purposes(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY ("cohortId", "tripPurposeId")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ─── Policy Engine ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policies (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
|
||||||
|
policy_name VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
status VARCHAR NOT NULL DEFAULT 'draft',
|
||||||
|
version INT NOT NULL DEFAULT 1,
|
||||||
|
audience_type VARCHAR NOT NULL DEFAULT 'ALL',
|
||||||
|
created_by UUID,
|
||||||
|
updated_by UUID,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_jurisdictions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
policy_id UUID NOT NULL REFERENCES policy_engine.tbl_policies(id) ON DELETE CASCADE,
|
||||||
|
jurisdiction_id UUID NOT NULL REFERENCES masters_lookup.tbl_jurisdictions(id) ON DELETE CASCADE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_target_audiences (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
policy_id UUID NOT NULL REFERENCES policy_engine.tbl_policies(id) ON DELETE CASCADE,
|
||||||
|
target_type VARCHAR NOT NULL,
|
||||||
|
target_id UUID
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_rules (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
policy_id UUID NOT NULL REFERENCES policy_engine.tbl_policies(id) ON DELETE CASCADE,
|
||||||
|
rule_category_id UUID REFERENCES masters_rule_engine.tbl_rules_categories(id) ON DELETE SET NULL,
|
||||||
|
priority INT NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_rule_conditions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
rule_id UUID NOT NULL REFERENCES policy_engine.tbl_policy_rules(id) ON DELETE CASCADE,
|
||||||
|
field_id UUID NOT NULL,
|
||||||
|
operator_id UUID NOT NULL,
|
||||||
|
value_text TEXT,
|
||||||
|
logical_operator VARCHAR NOT NULL DEFAULT 'AND',
|
||||||
|
sequence INT NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_actions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
rule_id UUID NOT NULL REFERENCES policy_engine.tbl_policy_rules(id) ON DELETE CASCADE,
|
||||||
|
action_type_id UUID NOT NULL REFERENCES masters_action_builder.tbl_action_types(id) ON DELETE CASCADE,
|
||||||
|
sequence INT NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS policy_engine.tbl_policy_action_values (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
action_id UUID NOT NULL REFERENCES policy_engine.tbl_policy_actions(id) ON DELETE CASCADE,
|
||||||
|
field_definition_id UUID REFERENCES masters_action_builder.tbl_field_definitions(id) ON DELETE SET NULL,
|
||||||
|
field_code VARCHAR NOT NULL,
|
||||||
|
value_index INT NOT NULL DEFAULT 0,
|
||||||
|
selected_value_id VARCHAR,
|
||||||
|
text_value TEXT,
|
||||||
|
number_value NUMERIC,
|
||||||
|
boolean_value BOOLEAN,
|
||||||
|
date_value DATE,
|
||||||
|
time_value TIME,
|
||||||
|
timestamp_value TIMESTAMP WITH TIME ZONE,
|
||||||
|
currency_code_id UUID,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tbl_policy_action_values_action
|
||||||
|
ON policy_engine.tbl_policy_action_values(action_id);
|
||||||
@@ -0,0 +1,939 @@
|
|||||||
|
-- =============================================================================
|
||||||
|
-- AeroResolve Master Data Seed Script
|
||||||
|
-- PostgreSQL 14+
|
||||||
|
-- =============================================================================
|
||||||
|
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_lookup;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_rule_engine;
|
||||||
|
CREATE SCHEMA IF NOT EXISTS masters_action_builder;
|
||||||
|
|
||||||
|
-- 1. Action Categories
|
||||||
|
INSERT INTO masters_action_builder.tbl_action_categories (code, name, "displayOrder", "isActive")
|
||||||
|
SELECT code, name, displayOrder, true FROM (VALUES
|
||||||
|
('REFUNDS', 'Refunds', 1),
|
||||||
|
('CASH_COMPENSATION', 'Cash Compensation', 2),
|
||||||
|
('TRAVEL_CREDITS', 'Travel Credits', 3),
|
||||||
|
('LOYALTY_BENEFITS', 'Loyalty Benefits', 4),
|
||||||
|
('ACCOMMODATION', 'Accommodation', 5),
|
||||||
|
('MEALS', 'Meals', 6),
|
||||||
|
('TRANSPORTATION', 'Transportation', 7),
|
||||||
|
('REBOOKING_TRAVEL', 'Rebooking & Travel', 8),
|
||||||
|
('UPGRADES', 'Upgrades', 9),
|
||||||
|
('ANCILLARY_RECOVERY', 'Ancillary Recovery', 10),
|
||||||
|
('COMMUNICATION', 'Communication', 11),
|
||||||
|
('WORKFLOW', 'Workflow', 12),
|
||||||
|
('FINANCE', 'Finance', 13),
|
||||||
|
('SYSTEM_INTEGRATION', 'System Integration', 14)
|
||||||
|
) AS t(code, name, displayOrder)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_action_builder.tbl_action_categories WHERE masters_action_builder.tbl_action_categories.code = t.code);
|
||||||
|
|
||||||
|
-- 2. Action Types
|
||||||
|
INSERT INTO masters_action_builder.tbl_action_types (code, "categoryId", name, "displayOrder", "isActive")
|
||||||
|
SELECT v.code, c.id, v.name, v.display_order, true
|
||||||
|
FROM (VALUES
|
||||||
|
-- Refunds
|
||||||
|
('FULL_TICKET_REFUND', 'REFUNDS', 'Full Ticket Refund', 1),
|
||||||
|
('PARTIAL_TICKET_REFUND', 'REFUNDS', 'Partial Ticket Refund', 2),
|
||||||
|
('TAX_REFUND', 'REFUNDS', 'Tax Refund', 3),
|
||||||
|
('ANCILLARY_REFUND', 'REFUNDS', 'Ancillary Refund', 4),
|
||||||
|
('BAGGAGE_FEE_REFUND', 'REFUNDS', 'Baggage Fee Refund', 5),
|
||||||
|
('CABIN_DOWNGRADE_REFUND', 'REFUNDS', 'Cabin Downgrade Refund', 6),
|
||||||
|
|
||||||
|
-- Cash Compensation
|
||||||
|
('REGULATORY_COMPENSATION', 'CASH_COMPENSATION', 'Regulatory Compensation', 1),
|
||||||
|
('AIRLINE_GOODWILL_CASH', 'CASH_COMPENSATION', 'Airline Goodwill Cash', 2),
|
||||||
|
('EX_GRATIA_COMPENSATION', 'CASH_COMPENSATION', 'Ex-Gratia Compensation', 3),
|
||||||
|
|
||||||
|
-- Travel Credits
|
||||||
|
('TRAVEL_VOUCHER', 'TRAVEL_CREDITS', 'Travel Voucher', 1),
|
||||||
|
('FUTURE_TRAVEL_CREDIT', 'TRAVEL_CREDITS', 'Future Travel Credit', 2),
|
||||||
|
('PROMO_CODE', 'TRAVEL_CREDITS', 'Promo Code', 3),
|
||||||
|
('DISCOUNT_COUPON', 'TRAVEL_CREDITS', 'Discount Coupon', 4),
|
||||||
|
|
||||||
|
-- Loyalty Benefits
|
||||||
|
('AWARD_MILES', 'LOYALTY_BENEFITS', 'Award Miles', 1),
|
||||||
|
('BONUS_MILES', 'LOYALTY_BENEFITS', 'Bonus Miles', 2),
|
||||||
|
('TIER_POINTS', 'LOYALTY_BENEFITS', 'Tier Points', 3),
|
||||||
|
('TIER_UPGRADE', 'LOYALTY_BENEFITS', 'Tier Upgrade', 4),
|
||||||
|
|
||||||
|
-- Accommodation
|
||||||
|
('HOTEL_ACCOMMODATION', 'ACCOMMODATION', 'Hotel Accommodation', 1),
|
||||||
|
('AIRPORT_HOTEL', 'ACCOMMODATION', 'Airport Hotel', 2),
|
||||||
|
|
||||||
|
-- Meals
|
||||||
|
('MEAL_VOUCHER', 'MEALS', 'Meal Voucher', 1),
|
||||||
|
('RESTAURANT_VOUCHER', 'MEALS', 'Restaurant Voucher', 2),
|
||||||
|
('REFRESHMENT_COUPON', 'MEALS', 'Refreshment Coupon', 3),
|
||||||
|
|
||||||
|
-- Transportation
|
||||||
|
('TAXI', 'TRANSPORTATION', 'Taxi', 1),
|
||||||
|
('AIRPORT_TRANSFER', 'TRANSPORTATION', 'Airport Transfer', 2),
|
||||||
|
('BUS_TRANSFER', 'TRANSPORTATION', 'Bus Transfer', 3),
|
||||||
|
('TRAIN_TICKET', 'TRANSPORTATION', 'Train Ticket', 4),
|
||||||
|
('CHAUFFEUR_SERVICE', 'TRANSPORTATION', 'Chauffeur Service', 5),
|
||||||
|
|
||||||
|
-- Rebooking & Travel
|
||||||
|
('AUTO_REBOOK', 'REBOOKING_TRAVEL', 'Auto Rebook', 1),
|
||||||
|
('PRIORITY_REBOOKING', 'REBOOKING_TRAVEL', 'Priority Rebooking', 2),
|
||||||
|
('OPEN_TICKET', 'REBOOKING_TRAVEL', 'Open Ticket', 3),
|
||||||
|
('ALTERNATE_AIRLINE', 'REBOOKING_TRAVEL', 'Alternate Airline', 4),
|
||||||
|
|
||||||
|
-- Upgrades
|
||||||
|
('CABIN_UPGRADE', 'UPGRADES', 'Cabin Upgrade', 1),
|
||||||
|
('SEAT_UPGRADE', 'UPGRADES', 'Seat Upgrade', 2),
|
||||||
|
('LOUNGE_ACCESS', 'UPGRADES', 'Lounge Access', 3),
|
||||||
|
('FAST_TRACK_SECURITY', 'UPGRADES', 'Fast Track Security', 4),
|
||||||
|
('PRIORITY_BOARDING', 'UPGRADES', 'Priority Boarding', 5),
|
||||||
|
|
||||||
|
-- Ancillary Recovery
|
||||||
|
('COMPLIMENTARY_WIFI', 'ANCILLARY_RECOVERY', 'Complimentary Wi-Fi', 1),
|
||||||
|
('FREE_BAGGAGE', 'ANCILLARY_RECOVERY', 'Free Baggage', 2),
|
||||||
|
('COMPLIMENTARY_MEAL', 'ANCILLARY_RECOVERY', 'Complimentary Meal', 3),
|
||||||
|
('SEAT_SELECTION', 'ANCILLARY_RECOVERY', 'Seat Selection', 4),
|
||||||
|
('CARBON_OFFSET_CREDIT', 'ANCILLARY_RECOVERY', 'Carbon Offset Credit', 5),
|
||||||
|
|
||||||
|
-- Communication
|
||||||
|
('PASSENGER_NOTIFICATION', 'COMMUNICATION', 'Passenger Notification', 1),
|
||||||
|
('AGENT_NOTIFICATION', 'COMMUNICATION', 'Agent Notification', 2),
|
||||||
|
('MANAGEMENT_ALERT', 'COMMUNICATION', 'Management Alert', 3),
|
||||||
|
|
||||||
|
-- Workflow
|
||||||
|
('AUTO_APPROVE', 'WORKFLOW', 'Auto Approve', 1),
|
||||||
|
('MANUAL_REVIEW', 'WORKFLOW', 'Manual Review', 2),
|
||||||
|
('ESCALATE', 'WORKFLOW', 'Escalate', 3),
|
||||||
|
('CREATE_CASE', 'WORKFLOW', 'Create Case', 4),
|
||||||
|
('HOLD_FOR_INVESTIGATION', 'WORKFLOW', 'Hold for Investigation', 5),
|
||||||
|
|
||||||
|
-- Finance
|
||||||
|
('TRIGGER_PAYMENT', 'FINANCE', 'Trigger Payment', 1),
|
||||||
|
('GENERATE_CREDIT_NOTE', 'FINANCE', 'Generate Credit Note', 2),
|
||||||
|
('GENERATE_INVOICE', 'FINANCE', 'Generate Invoice', 3),
|
||||||
|
('WRITE_OFF', 'FINANCE', 'Write-off', 4),
|
||||||
|
|
||||||
|
-- System Integration
|
||||||
|
('UPDATE_CRM', 'SYSTEM_INTEGRATION', 'Update CRM', 1),
|
||||||
|
('UPDATE_LOYALTY', 'SYSTEM_INTEGRATION', 'Update Loyalty', 2),
|
||||||
|
('UPDATE_PSS', 'SYSTEM_INTEGRATION', 'Update PSS', 3),
|
||||||
|
('CREATE_AUDIT_RECORD', 'SYSTEM_INTEGRATION', 'Create Audit Record', 4),
|
||||||
|
('TRIGGER_WEBHOOK_API', 'SYSTEM_INTEGRATION', 'Trigger Webhook / API', 5)
|
||||||
|
) AS v(code, cat_code, name, display_order)
|
||||||
|
JOIN masters_action_builder.tbl_action_categories c ON c.code = v.cat_code
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_action_builder.tbl_action_types WHERE masters_action_builder.tbl_action_types.code = v.code);
|
||||||
|
|
||||||
|
-- 3. Membership Tiers
|
||||||
|
INSERT INTO masters_lookup.tbl_membership_tiers (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Platinum', 'platinum'),
|
||||||
|
('Gold', 'gold'),
|
||||||
|
('Silver', 'silver'),
|
||||||
|
('Bronze', 'bronze'),
|
||||||
|
('Basic', 'basic'),
|
||||||
|
('Non-Member', 'non-member')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_membership_tiers WHERE masters_lookup.tbl_membership_tiers.value = t.value);
|
||||||
|
|
||||||
|
-- 4. Customer Values
|
||||||
|
INSERT INTO masters_lookup.tbl_customer_values (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('High Value', 'high'),
|
||||||
|
('Medium Value', 'medium'),
|
||||||
|
('Low Value', 'low')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_customer_values WHERE masters_lookup.tbl_customer_values.value = t.value);
|
||||||
|
|
||||||
|
-- 5. Regions
|
||||||
|
INSERT INTO masters_lookup.tbl_regions (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Global', 'global'),
|
||||||
|
('Americas', 'americas'),
|
||||||
|
('Europe', 'europe'),
|
||||||
|
('Middle East', 'middle-east'),
|
||||||
|
('Asia Pacific', 'asia-pacific'),
|
||||||
|
('Africa', 'africa')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_regions WHERE masters_lookup.tbl_regions.value = t.value);
|
||||||
|
|
||||||
|
-- 6. Trip Purposes
|
||||||
|
INSERT INTO masters_lookup.tbl_trip_purposes (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Business', 'business'),
|
||||||
|
('Leisure', 'leisure'),
|
||||||
|
('Corporate', 'corporate'),
|
||||||
|
('Government', 'government')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_trip_purposes WHERE masters_lookup.tbl_trip_purposes.value = t.value);
|
||||||
|
|
||||||
|
-- 7. Cabin Classes
|
||||||
|
INSERT INTO masters_lookup.tbl_cabin_classes (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('First Class', 'first-class'),
|
||||||
|
('Business Class', 'business-class'),
|
||||||
|
('Premium Economy', 'premium-economy'),
|
||||||
|
('Economy', 'economy')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_cabin_classes WHERE masters_lookup.tbl_cabin_classes.value = t.value);
|
||||||
|
|
||||||
|
-- 8. Passenger Types
|
||||||
|
INSERT INTO masters_lookup.tbl_passenger_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Adult', 'adult'),
|
||||||
|
('Child', 'child'),
|
||||||
|
('Infant', 'infant'),
|
||||||
|
('Senior Citizen', 'senior')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_passenger_types WHERE masters_lookup.tbl_passenger_types.value = t.value);
|
||||||
|
|
||||||
|
-- 9. Ancillary Purchases
|
||||||
|
INSERT INTO masters_lookup.tbl_ancillary_purchases (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Preferred Seat', 'preferred-seat'),
|
||||||
|
('Extra Legroom', 'extra-legroom'),
|
||||||
|
('Wi-Fi', 'wi-fi'),
|
||||||
|
('Lounge Access', 'lounge-access'),
|
||||||
|
('Priority Boarding', 'priority-boarding'),
|
||||||
|
('Fast Track', 'fast-track'),
|
||||||
|
('Paid Meal', 'paid-meal'),
|
||||||
|
('Special Meal', 'special-meal'),
|
||||||
|
('Extra Baggage', 'extra-baggage'),
|
||||||
|
('Upgrade Purchase', 'upgrade-purchase'),
|
||||||
|
('Airport Transfer', 'airport-transfer'),
|
||||||
|
('Chauffeur Service', 'chauffeur-service'),
|
||||||
|
('Sports Equipment', 'sports-equipment'),
|
||||||
|
('Musical Instrument', 'musical-instrument'),
|
||||||
|
('In-flight Entertainment', 'in-flight-entertainment'),
|
||||||
|
('Power Outlet', 'power-outlet'),
|
||||||
|
('Carbon Offset', 'carbon-offset')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_ancillary_purchases WHERE masters_lookup.tbl_ancillary_purchases.value = t.value);
|
||||||
|
|
||||||
|
-- 10. Revenue Segments
|
||||||
|
INSERT INTO masters_lookup.tbl_revenue_segments (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('High Value', 'high'),
|
||||||
|
('Medium Value', 'medium'),
|
||||||
|
('Low Value', 'low')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_revenue_segments WHERE masters_lookup.tbl_revenue_segments.value = t.value);
|
||||||
|
|
||||||
|
-- 11. Jurisdictions
|
||||||
|
INSERT INTO masters_lookup.tbl_jurisdictions (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('United Arab Emirates', 'uae'),
|
||||||
|
('European Union', 'eu'),
|
||||||
|
('United States', 'us'),
|
||||||
|
('United Kingdom', 'uk'),
|
||||||
|
('India', 'india'),
|
||||||
|
('Asia Pacific', 'apac'),
|
||||||
|
('Global', 'global')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_jurisdictions WHERE masters_lookup.tbl_jurisdictions.value = t.value);
|
||||||
|
|
||||||
|
|
||||||
|
-- 12. Rule Categories (Business Rule Categories)
|
||||||
|
DELETE FROM masters_rule_engine.tbl_rules_categories
|
||||||
|
WHERE code NOT IN (
|
||||||
|
'FLIGHT_OPERATIONS', 'BAGGAGE_ISSUES', 'CABIN_DOWNGRADES',
|
||||||
|
'ANCILLARY_FAILURES', 'DENIED_BOARDING', 'MISSED_CONNECTIONS'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO masters_rule_engine.tbl_rules_categories (code, name, description, "displayOrder", "isActive")
|
||||||
|
SELECT code, name, description, displayOrder, true FROM (VALUES
|
||||||
|
('FLIGHT_OPERATIONS', 'Flight Operations', 'Rules for flight disruptions, delays, cancellations, and diversions', 1),
|
||||||
|
('BAGGAGE_ISSUES', 'Baggage Issues', 'Rules for delayed, damaged, or lost baggage recovery', 2),
|
||||||
|
('CABIN_DOWNGRADES', 'Cabin Downgrades', 'Rules for involuntary cabin downgrades and seat reassignments', 3),
|
||||||
|
('ANCILLARY_FAILURES', 'Ancillary Failures', 'Rules for unfulfilled ancillary services like Wi-Fi, meals, seats', 4),
|
||||||
|
('DENIED_BOARDING', 'Denied Boarding', 'Rules for overbooking and involuntary denied boarding', 5),
|
||||||
|
('MISSED_CONNECTIONS', 'Missed Connections', 'Rules for tight connection failures and rebooking compensation', 6)
|
||||||
|
) AS t(code, name, description, displayOrder)
|
||||||
|
ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description;
|
||||||
|
|
||||||
|
-- 13. Booking Channels
|
||||||
|
INSERT INTO masters_lookup.tbl_booking_channels (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airline Website', 'airline-website'),
|
||||||
|
('Airline Mobile App', 'airline-mobile-app'),
|
||||||
|
('Airport Ticket Counter', 'airport-ticket-counter'),
|
||||||
|
('Call Center', 'call-center'),
|
||||||
|
('Corporate Booking Tool', 'corporate-booking-tool'),
|
||||||
|
('Global Distribution System', 'global-distribution-system'),
|
||||||
|
('Online Travel Agency', 'online-travel-agency'),
|
||||||
|
('Travel Agent', 'travel-agent')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_booking_channels WHERE masters_lookup.tbl_booking_channels.value = t.value);
|
||||||
|
|
||||||
|
-- 14. Flight Types
|
||||||
|
INSERT INTO masters_lookup.tbl_flight_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Domestic', 'domestic'),
|
||||||
|
('International', 'international')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_flight_types WHERE masters_lookup.tbl_flight_types.value = t.value);
|
||||||
|
|
||||||
|
-- 15. Journey Types
|
||||||
|
INSERT INTO masters_lookup.tbl_journey_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('One Way', 'one-way'),
|
||||||
|
('Round Trip', 'round-trip'),
|
||||||
|
('Multi City', 'multi-city')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_journey_types WHERE masters_lookup.tbl_journey_types.value = t.value);
|
||||||
|
|
||||||
|
-- 16. Fare Flexibilities
|
||||||
|
INSERT INTO masters_lookup.tbl_fare_flexibilities (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Non Refundable', 'non-refundable'),
|
||||||
|
('Partially Refundable', 'partially-refundable'),
|
||||||
|
('Refundable', 'refundable'),
|
||||||
|
('Exchangeable', 'exchangeable'),
|
||||||
|
('Non Changeable', 'non-changeable')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_fare_flexibilities WHERE masters_lookup.tbl_fare_flexibilities.value = t.value);
|
||||||
|
|
||||||
|
-- 17. Carrier Types
|
||||||
|
INSERT INTO masters_lookup.tbl_carrier_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Operating Carrier', 'operating-carrier'),
|
||||||
|
('Marketing Carrier', 'marketing-carrier'),
|
||||||
|
('Partner Carrier', 'partner-carrier'),
|
||||||
|
('Regional Carrier', 'regional-carrier'),
|
||||||
|
('Low Cost Carrier', 'low-cost-carrier'),
|
||||||
|
('Full Service Carrier', 'full-service-carrier'),
|
||||||
|
('Charter Carrier', 'charter-carrier')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_carrier_types WHERE masters_lookup.tbl_carrier_types.value = t.value);
|
||||||
|
|
||||||
|
-- 18. Special Assistance Types
|
||||||
|
INSERT INTO masters_lookup.tbl_special_assistance_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Wheelchair Assistance', 'wheelchair-assistance'),
|
||||||
|
('Wheelchair Ramp', 'wheelchair-ramp'),
|
||||||
|
('Wheelchair Steps', 'wheelchair-steps'),
|
||||||
|
('Wheelchair Cabin', 'wheelchair-cabin'),
|
||||||
|
('Blind Passenger', 'blind-passenger'),
|
||||||
|
('Deaf Passenger', 'deaf-passenger'),
|
||||||
|
('Medical Assistance', 'medical-assistance'),
|
||||||
|
('Oxygen Required', 'oxygen-required'),
|
||||||
|
('Stretcher', 'stretcher'),
|
||||||
|
('Unaccompanied Minor', 'unaccompanied-minor'),
|
||||||
|
('Service Animal', 'service-animal'),
|
||||||
|
('Pregnant Passenger', 'pregnant-passenger'),
|
||||||
|
('Elderly Passenger', 'elderly-passenger'),
|
||||||
|
('Other', 'other')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_special_assistance_types WHERE masters_lookup.tbl_special_assistance_types.value = t.value);
|
||||||
|
|
||||||
|
-- 19. Delay Reasons
|
||||||
|
INSERT INTO masters_lookup.tbl_delay_reasons (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Air Traffic Control Restriction', 'air-traffic-control-restriction'),
|
||||||
|
('Aircraft Rotation', 'aircraft-rotation'),
|
||||||
|
('Airport Congestion', 'airport-congestion'),
|
||||||
|
('Crew Availability', 'crew-availability'),
|
||||||
|
('Customs Delay', 'customs-delay'),
|
||||||
|
('Fueling Delay', 'fueling-delay'),
|
||||||
|
('Late Arrival of Aircraft', 'late-arrival-of-aircraft'),
|
||||||
|
('Operational Decision', 'operational-decision'),
|
||||||
|
('Passenger Handling', 'passenger-handling'),
|
||||||
|
('Runway Closure', 'runway-closure'),
|
||||||
|
('Security', 'security'),
|
||||||
|
('Severe Weather', 'severe-weather'),
|
||||||
|
('Technical Fault', 'technical-fault'),
|
||||||
|
('Other', 'other')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_delay_reasons WHERE masters_lookup.tbl_delay_reasons.value = t.value);
|
||||||
|
|
||||||
|
-- 20. Delay Durations
|
||||||
|
INSERT INTO masters_lookup.tbl_delay_durations (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Less than 1 Hour', 'less-than-1-hour'),
|
||||||
|
('1-2 Hours', '1-2-hours'),
|
||||||
|
('2-3 Hours', '2-3-hours'),
|
||||||
|
('3-4 Hours', '3-4-hours'),
|
||||||
|
('More than 4 Hours', 'more-than-4-hours')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_delay_durations WHERE masters_lookup.tbl_delay_durations.value = t.value);
|
||||||
|
|
||||||
|
-- 21. Extraordinary Circumstances
|
||||||
|
INSERT INTO masters_lookup.tbl_extraordinary_circumstances (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Air Traffic Management Decision', 'air-traffic-management-decision'),
|
||||||
|
('Airport Closure', 'airport-closure'),
|
||||||
|
('Bird Strike', 'bird-strike'),
|
||||||
|
('Civil Unrest', 'civil-unrest'),
|
||||||
|
('Medical Emergency', 'medical-emergency'),
|
||||||
|
('Political Instability', 'political-instability'),
|
||||||
|
('Security Threat', 'security-threat'),
|
||||||
|
('Severe Weather', 'severe-weather'),
|
||||||
|
('Strike (External)', 'strike-external-'),
|
||||||
|
('War', 'war'),
|
||||||
|
('Other', 'other')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_extraordinary_circumstances WHERE masters_lookup.tbl_extraordinary_circumstances.value = t.value);
|
||||||
|
|
||||||
|
-- 22. Cancellation Reasons
|
||||||
|
INSERT INTO masters_lookup.tbl_cancellation_reasons (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Air Traffic Control Restriction', 'air-traffic-control-restriction'),
|
||||||
|
('Airport Closure', 'airport-closure'),
|
||||||
|
('Commercial Decision', 'commercial-decision'),
|
||||||
|
('Crew Availability', 'crew-availability'),
|
||||||
|
('Operational Decision', 'operational-decision'),
|
||||||
|
('Overbooking', 'overbooking'),
|
||||||
|
('Security', 'security'),
|
||||||
|
('Severe Weather', 'severe-weather'),
|
||||||
|
('Strike', 'strike'),
|
||||||
|
('Technical Fault', 'technical-fault')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_cancellation_reasons WHERE masters_lookup.tbl_cancellation_reasons.value = t.value);
|
||||||
|
|
||||||
|
-- 23. Diversion Reasons
|
||||||
|
INSERT INTO masters_lookup.tbl_diversion_reasons (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airport Closure', 'airport-closure'),
|
||||||
|
('Destination Weather', 'destination-weather'),
|
||||||
|
('Fuel Emergency', 'fuel-emergency'),
|
||||||
|
('Medical Emergency', 'medical-emergency'),
|
||||||
|
('Runway Obstruction', 'runway-obstruction'),
|
||||||
|
('Security Threat', 'security-threat'),
|
||||||
|
('Technical Fault', 'technical-fault')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_diversion_reasons WHERE masters_lookup.tbl_diversion_reasons.value = t.value);
|
||||||
|
|
||||||
|
-- 24. Missed Connection Reasons
|
||||||
|
INSERT INTO masters_lookup.tbl_missed_connection_reasons (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Customs Delay', 'customs-delay'),
|
||||||
|
('Flight Delay', 'flight-delay'),
|
||||||
|
('Immigration Delay', 'immigration-delay'),
|
||||||
|
('Passenger Delay', 'passenger-delay'),
|
||||||
|
('Security Screening Delay', 'security-screening-delay')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_missed_connection_reasons WHERE masters_lookup.tbl_missed_connection_reasons.value = t.value);
|
||||||
|
|
||||||
|
-- 25. Compensation Eligibilities
|
||||||
|
INSERT INTO masters_lookup.tbl_compensation_eligibilities (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Eligible', 'eligible'),
|
||||||
|
('Not Eligible', 'not-eligible'),
|
||||||
|
('Requires Manual Review', 'requires-manual-review')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_compensation_eligibilities WHERE masters_lookup.tbl_compensation_eligibilities.value = t.value);
|
||||||
|
|
||||||
|
-- 26. Compensation Types
|
||||||
|
INSERT INTO masters_lookup.tbl_compensation_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Cash', 'cash'),
|
||||||
|
('Cheque', 'cheque'),
|
||||||
|
('Flight Voucher', 'flight-voucher'),
|
||||||
|
('Loyalty Miles', 'loyalty-miles'),
|
||||||
|
('Meal Voucher', 'meal-voucher'),
|
||||||
|
('Hotel Accommodation', 'hotel-accommodation'),
|
||||||
|
('Ground Transport', 'ground-transport')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_compensation_types WHERE masters_lookup.tbl_compensation_types.value = t.value);
|
||||||
|
|
||||||
|
-- 27. Refund Types
|
||||||
|
INSERT INTO masters_lookup.tbl_refund_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Full Refund', 'full-refund'),
|
||||||
|
('Partial Refund', 'partial-refund'),
|
||||||
|
('Future Travel Credit', 'future-travel-credit'),
|
||||||
|
('Travel Voucher', 'travel-voucher'),
|
||||||
|
('Tax Refund Only', 'tax-refund-only'),
|
||||||
|
('Telephone Reimbursement', 'telephone-reimbursement')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_refund_types WHERE masters_lookup.tbl_refund_types.value = t.value);
|
||||||
|
|
||||||
|
-- 28. Flight Disruption Types
|
||||||
|
INSERT INTO masters_lookup.tbl_flight_disruption_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Cancellation', 'cancellation'),
|
||||||
|
('Delay', 'delay'),
|
||||||
|
('Denied Boarding', 'denied-boarding'),
|
||||||
|
('Diversion', 'diversion'),
|
||||||
|
('Missed Connection', 'missed-connection')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_flight_disruption_types WHERE masters_lookup.tbl_flight_disruption_types.value = t.value);
|
||||||
|
|
||||||
|
-- 29. Airline Responsibilities
|
||||||
|
INSERT INTO masters_lookup.tbl_airline_responsibilities (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airline Responsible', 'airline-responsible'),
|
||||||
|
('Airport Responsible', 'airport-responsible'),
|
||||||
|
('ATC Responsible', 'atc-responsible'),
|
||||||
|
('Passenger Responsible', 'passenger-responsible'),
|
||||||
|
('Shared Responsibility', 'shared-responsibility'),
|
||||||
|
('Third Party Responsible', 'third-party-responsible'),
|
||||||
|
('Snow', 'snow')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_airline_responsibilities WHERE masters_lookup.tbl_airline_responsibilities.value = t.value);
|
||||||
|
|
||||||
|
-- 30. Weather Conditions
|
||||||
|
INSERT INTO masters_lookup.tbl_weather_conditions (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Fog', 'fog'),
|
||||||
|
('Heavy Rain', 'heavy-rain'),
|
||||||
|
('Hurricane', 'hurricane'),
|
||||||
|
('Ice', 'ice'),
|
||||||
|
('Lightning', 'lightning'),
|
||||||
|
('Sandstorm', 'sandstorm'),
|
||||||
|
('Thunderstorm', 'thunderstorm')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_weather_conditions WHERE masters_lookup.tbl_weather_conditions.value = t.value);
|
||||||
|
|
||||||
|
-- 31. ATC Restrictions
|
||||||
|
INSERT INTO masters_lookup.tbl_atc_restrictions (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airspace Closure', 'airspace-closure'),
|
||||||
|
('Flow Control', 'flow-control'),
|
||||||
|
('Ground Stop', 'ground-stop'),
|
||||||
|
('Slot Restriction', 'slot-restriction'),
|
||||||
|
('Traffic Congestion', 'traffic-congestion'),
|
||||||
|
('Navigation System', 'navigation-system')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_atc_restrictions WHERE masters_lookup.tbl_atc_restrictions.value = t.value);
|
||||||
|
|
||||||
|
-- 32. Technical Fault Categories
|
||||||
|
INSERT INTO masters_lookup.tbl_technical_fault_categories (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Aircraft Damage', 'aircraft-damage'),
|
||||||
|
('Avionics', 'avionics'),
|
||||||
|
('Cabin Systems', 'cabin-systems'),
|
||||||
|
('Engine', 'engine'),
|
||||||
|
('Hydraulic System', 'hydraulic-system'),
|
||||||
|
('Landing Gear', 'landing-gear'),
|
||||||
|
('Volcanic Ash', 'volcanic-ash'),
|
||||||
|
('Wind Shear', 'wind-shear')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_technical_fault_categories WHERE masters_lookup.tbl_technical_fault_categories.value = t.value);
|
||||||
|
|
||||||
|
-- 33. Operators
|
||||||
|
INSERT INTO masters_rule_engine.tbl_operators (code, name, symbol, "displayOrder", "isActive")
|
||||||
|
SELECT code, name, symbol, displayOrder, true FROM (VALUES
|
||||||
|
('EQ', 'Equals', '=', 1),
|
||||||
|
('NE', 'Not Equals', '!=', 2),
|
||||||
|
('GT', 'Greater Than', '>', 3),
|
||||||
|
('GTE', 'Greater Than or Equal', '>=', 4),
|
||||||
|
('LT', 'Less Than', '<', 5),
|
||||||
|
('LTE', 'Less Than or Equal', '<=', 6),
|
||||||
|
('BETWEEN', 'Between', 'BETWEEN', 7),
|
||||||
|
('CONTAINS', 'Contains', 'CONTAINS', 8),
|
||||||
|
('IN', 'In', 'IN', 9),
|
||||||
|
('IS_EMPTY', 'Is Empty', 'IS EMPTY', 10)
|
||||||
|
) AS t(code, name, symbol, displayOrder)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_rule_engine.tbl_operators WHERE masters_rule_engine.tbl_operators.code = t.code);
|
||||||
|
|
||||||
|
-- 34. Refund Bases
|
||||||
|
INSERT INTO masters_lookup.tbl_refund_bases (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Base Fare', 'base-fare'),
|
||||||
|
('Taxes', 'taxes'),
|
||||||
|
('Total Fare', 'total-fare')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_refund_bases WHERE masters_lookup.tbl_refund_bases.value = t.value);
|
||||||
|
|
||||||
|
-- 35. Currencies
|
||||||
|
INSERT INTO masters_lookup.tbl_currencies (label, value, symbol, "isActive")
|
||||||
|
SELECT label, value, symbol, true FROM (VALUES
|
||||||
|
('United States Dollar', 'USD', '$'),
|
||||||
|
('Euro', 'EUR', '€'),
|
||||||
|
('British Pound', 'GBP', '£'),
|
||||||
|
('United Arab Emirates Dirham', 'AED', 'AED'),
|
||||||
|
('Saudi Riyal', 'SAR', 'SAR'),
|
||||||
|
('Indian Rupee', 'INR', '₹'),
|
||||||
|
('Japanese Yen', 'JPY', '¥'),
|
||||||
|
('Canadian Dollar', 'CAD', '$'),
|
||||||
|
('Australian Dollar', 'AUD', '$'),
|
||||||
|
('Swiss Franc', 'CHF', 'CHF'),
|
||||||
|
('Singapore Dollar', 'SGD', '$'),
|
||||||
|
('Qatari Riyal', 'QAR', 'QAR'),
|
||||||
|
('Kuwaiti Dinar', 'KWD', 'KWD'),
|
||||||
|
('Bahraini Dinar', 'BHD', 'BHD'),
|
||||||
|
('Omani Rial', 'OMR', 'OMR')
|
||||||
|
) AS t(label, value, symbol)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_currencies WHERE masters_lookup.tbl_currencies.value = t.value);
|
||||||
|
|
||||||
|
-- 36. Refund Methods
|
||||||
|
INSERT INTO masters_lookup.tbl_refund_methods (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Original Payment Method', 'original-payment-method'),
|
||||||
|
('Wallet', 'wallet'),
|
||||||
|
('Bank Transfer', 'bank-transfer'),
|
||||||
|
('Voucher', 'voucher')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_refund_methods WHERE masters_lookup.tbl_refund_methods.value = t.value);
|
||||||
|
|
||||||
|
-- 37. Amount Types
|
||||||
|
INSERT INTO masters_lookup.tbl_amount_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Fixed', 'fixed'),
|
||||||
|
('Percentage', 'percentage'),
|
||||||
|
('Formula', 'formula')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_amount_types WHERE masters_lookup.tbl_amount_types.value = t.value);
|
||||||
|
|
||||||
|
-- =============================================================================
|
||||||
|
-- 38. Condition Groups (Level 2)
|
||||||
|
-- =============================================================================
|
||||||
|
INSERT INTO masters_rule_engine.tbl_condition_groups (code, name, "displayOrder", "isActive")
|
||||||
|
SELECT code, name, displayOrder, true FROM (VALUES
|
||||||
|
('FLIGHT', 'Flight Details', 1),
|
||||||
|
('DISRUPTION', 'Disruption Details', 2),
|
||||||
|
('PASSENGER', 'Passenger Profile', 3),
|
||||||
|
('JOURNEY', 'Journey & Itinerary', 4),
|
||||||
|
('BOOKING', 'Booking & Fare', 5),
|
||||||
|
('BAGGAGE', 'Baggage Details', 6),
|
||||||
|
('CABIN', 'Cabin & Seating', 7),
|
||||||
|
('ANCILLARY', 'Ancillary Service Details', 8)
|
||||||
|
) AS t(code, name, displayOrder)
|
||||||
|
ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name;
|
||||||
|
|
||||||
|
-- =============================================================================
|
||||||
|
-- 40. Rule Category Groups Mapping (Level 1 -> Level 2)
|
||||||
|
-- =============================================================================
|
||||||
|
INSERT INTO masters_rule_engine.tbl_rule_category_groups ("ruleCategoryId", "conditionGroupId")
|
||||||
|
SELECT c.id, g.id
|
||||||
|
FROM (VALUES
|
||||||
|
('FLIGHT_OPERATIONS', 'FLIGHT'),
|
||||||
|
('FLIGHT_OPERATIONS', 'DISRUPTION'),
|
||||||
|
('FLIGHT_OPERATIONS', 'PASSENGER'),
|
||||||
|
('FLIGHT_OPERATIONS', 'JOURNEY'),
|
||||||
|
('FLIGHT_OPERATIONS', 'BOOKING'),
|
||||||
|
('BAGGAGE_ISSUES', 'PASSENGER'),
|
||||||
|
('BAGGAGE_ISSUES', 'JOURNEY'),
|
||||||
|
('BAGGAGE_ISSUES', 'BAGGAGE'),
|
||||||
|
('CABIN_DOWNGRADES', 'PASSENGER'),
|
||||||
|
('CABIN_DOWNGRADES', 'JOURNEY'),
|
||||||
|
('CABIN_DOWNGRADES', 'CABIN'),
|
||||||
|
('CABIN_DOWNGRADES', 'BOOKING'),
|
||||||
|
('ANCILLARY_FAILURES', 'PASSENGER'),
|
||||||
|
('ANCILLARY_FAILURES', 'ANCILLARY'),
|
||||||
|
('ANCILLARY_FAILURES', 'BOOKING'),
|
||||||
|
('DENIED_BOARDING', 'FLIGHT'),
|
||||||
|
('DENIED_BOARDING', 'PASSENGER'),
|
||||||
|
('DENIED_BOARDING', 'JOURNEY'),
|
||||||
|
('DENIED_BOARDING', 'BOOKING'),
|
||||||
|
('MISSED_CONNECTIONS', 'FLIGHT'),
|
||||||
|
('MISSED_CONNECTIONS', 'PASSENGER'),
|
||||||
|
('MISSED_CONNECTIONS', 'JOURNEY'),
|
||||||
|
('MISSED_CONNECTIONS', 'BOOKING')
|
||||||
|
) AS v(cat_code, group_code)
|
||||||
|
JOIN masters_rule_engine.tbl_rules_categories c ON c.code = v.cat_code
|
||||||
|
JOIN masters_rule_engine.tbl_condition_groups g ON g.code = v.group_code
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM masters_rule_engine.tbl_rule_category_groups rcg
|
||||||
|
WHERE rcg."ruleCategoryId" = c.id AND rcg."conditionGroupId" = g.id
|
||||||
|
);
|
||||||
|
|
||||||
|
-- =============================================================================
|
||||||
|
-- 41. Condition Fields (Level 3)
|
||||||
|
-- =============================================================================
|
||||||
|
INSERT INTO masters_rule_engine.tbl_condition_fields ("groupId", code, name, "lookupTable", "dataType", "operatorType", "displayOrder", "isActive")
|
||||||
|
SELECT g.id, v.code, v.name, v.lookup_table, v.data_type, v.operator_type, v.display_order, true
|
||||||
|
FROM (VALUES
|
||||||
|
-- FLIGHT
|
||||||
|
('FLIGHT', 'flight_type', 'Flight Type', 'tbl_flight_types', 'ENUM', 'COMPARISON', 1),
|
||||||
|
('FLIGHT', 'origin_airport', 'Origin Airport', NULL, 'STRING', 'TEXT', 2),
|
||||||
|
('FLIGHT', 'destination_airport', 'Destination Airport', NULL, 'STRING', 'TEXT', 3),
|
||||||
|
('FLIGHT', 'operating_carrier', 'Operating Carrier', 'tbl_carrier_types', 'ENUM', 'COMPARISON', 4),
|
||||||
|
('FLIGHT', 'marketing_carrier', 'Marketing Carrier', 'tbl_carrier_types', 'ENUM', 'COMPARISON', 5),
|
||||||
|
('FLIGHT', 'flight_distance', 'Flight Distance (km)', NULL, 'NUMBER', 'COMPARISON', 6),
|
||||||
|
|
||||||
|
-- DISRUPTION
|
||||||
|
('DISRUPTION', 'delay_duration', 'Delay Duration (mins)', 'tbl_delay_durations', 'NUMBER', 'COMPARISON', 1),
|
||||||
|
('DISRUPTION', 'delay_reason', 'Delay Reason', 'tbl_delay_reasons', 'ENUM', 'SET', 2),
|
||||||
|
('DISRUPTION', 'cancellation_reason', 'Cancellation Reason', 'tbl_cancellation_reasons', 'ENUM', 'SET', 3),
|
||||||
|
('DISRUPTION', 'diversion_reason', 'Diversion Reason', 'tbl_diversion_reasons', 'ENUM', 'SET', 4),
|
||||||
|
('DISRUPTION', 'weather_condition', 'Weather Condition', 'tbl_weather_conditions', 'ENUM', 'SET', 5),
|
||||||
|
('DISRUPTION', 'atc_restriction', 'ATC Restriction', 'tbl_atc_restrictions', 'ENUM', 'SET', 6),
|
||||||
|
('DISRUPTION', 'technical_fault', 'Technical Fault', 'tbl_technical_fault_categories', 'ENUM', 'SET', 7),
|
||||||
|
('DISRUPTION', 'extraordinary_circumstance', 'Extraordinary Circumstance', 'tbl_extraordinary_circumstances', 'ENUM', 'SET', 8),
|
||||||
|
('DISRUPTION', 'airline_responsibility', 'Airline Responsibility', 'tbl_airline_responsibilities', 'ENUM', 'COMPARISON', 9),
|
||||||
|
|
||||||
|
-- PASSENGER
|
||||||
|
('PASSENGER', 'passenger_type', 'Passenger Type', 'tbl_passenger_types', 'ENUM', 'SET', 1),
|
||||||
|
('PASSENGER', 'cabin_class', 'Cabin Class', 'tbl_cabin_classes', 'ENUM', 'SET', 2),
|
||||||
|
('PASSENGER', 'membership_tier', 'Membership Tier', 'tbl_membership_tiers', 'ENUM', 'SET', 3),
|
||||||
|
('PASSENGER', 'loyalty_tier', 'Loyalty Tier', 'tbl_membership_tiers', 'ENUM', 'SET', 4),
|
||||||
|
('PASSENGER', 'customer_value', 'Customer Value', 'tbl_customer_values', 'ENUM', 'COMPARISON', 5),
|
||||||
|
('PASSENGER', 'corporate_customer', 'Corporate Customer', NULL, 'BOOLEAN', 'BOOLEAN', 6),
|
||||||
|
('PASSENGER', 'group_booking', 'Group Booking', NULL, 'BOOLEAN', 'BOOLEAN', 7),
|
||||||
|
('PASSENGER', 'special_assistance', 'Special Assistance Type', 'tbl_special_assistance_types', 'ENUM', 'SET', 8),
|
||||||
|
|
||||||
|
-- JOURNEY
|
||||||
|
('JOURNEY', 'journey_type', 'Journey Type', 'tbl_journey_types', 'ENUM', 'COMPARISON', 1),
|
||||||
|
('JOURNEY', 'protected_connection', 'Protected Connection', NULL, 'BOOLEAN', 'BOOLEAN', 2),
|
||||||
|
('JOURNEY', 'self_transfer', 'Self Transfer', NULL, 'BOOLEAN', 'BOOLEAN', 3),
|
||||||
|
('JOURNEY', 'number_of_segments', 'Number Of Segments', NULL, 'NUMBER', 'COMPARISON', 4),
|
||||||
|
('JOURNEY', 'final_destination_delay', 'Final Destination Delay (mins)', NULL, 'NUMBER', 'COMPARISON', 5),
|
||||||
|
|
||||||
|
-- BOOKING
|
||||||
|
('BOOKING', 'booking_channel', 'Booking Channel', 'tbl_booking_channels', 'ENUM', 'SET', 1),
|
||||||
|
('BOOKING', 'refundable_ticket', 'Refundable Ticket', NULL, 'BOOLEAN', 'BOOLEAN', 2),
|
||||||
|
('BOOKING', 'fare_flexibility', 'Fare Flexibility', 'tbl_fare_flexibilities', 'ENUM', 'COMPARISON', 3),
|
||||||
|
('BOOKING', 'ticket_value', 'Ticket Value', NULL, 'NUMBER', 'COMPARISON', 4),
|
||||||
|
('BOOKING', 'ancillary_purchased', 'Ancillary Purchased', 'tbl_ancillary_purchases', 'ENUM', 'SET', 5),
|
||||||
|
|
||||||
|
-- BAGGAGE
|
||||||
|
('BAGGAGE', 'bag_status', 'Bag Status', NULL, 'STRING', 'TEXT', 1),
|
||||||
|
('BAGGAGE', 'bag_type', 'Bag Type', NULL, 'STRING', 'TEXT', 2),
|
||||||
|
('BAGGAGE', 'bag_delay', 'Bag Delay Duration (hrs)', NULL, 'NUMBER', 'COMPARISON', 3),
|
||||||
|
('BAGGAGE', 'bag_value', 'Bag Value', NULL, 'NUMBER', 'COMPARISON', 4),
|
||||||
|
('BAGGAGE', 'pir_created', 'PIR Created', NULL, 'BOOLEAN', 'BOOLEAN', 5),
|
||||||
|
|
||||||
|
-- CABIN
|
||||||
|
('CABIN', 'original_cabin', 'Original Cabin', 'tbl_cabin_classes', 'ENUM', 'COMPARISON', 1),
|
||||||
|
('CABIN', 'assigned_cabin', 'Assigned Cabin', 'tbl_cabin_classes', 'ENUM', 'COMPARISON', 2),
|
||||||
|
('CABIN', 'downgrade_level', 'Downgrade Level', NULL, 'NUMBER', 'COMPARISON', 3),
|
||||||
|
('CABIN', 'seat_type', 'Seat Type', NULL, 'STRING', 'TEXT', 4),
|
||||||
|
|
||||||
|
-- ANCILLARY
|
||||||
|
('ANCILLARY', 'ancillary_type', 'Ancillary Type', 'tbl_ancillary_purchases', 'ENUM', 'SET', 1),
|
||||||
|
('ANCILLARY', 'ancillary_delivered', 'Ancillary Delivered', NULL, 'BOOLEAN', 'BOOLEAN', 2),
|
||||||
|
('ANCILLARY', 'service_value', 'Service Value', NULL, 'NUMBER', 'COMPARISON', 3)
|
||||||
|
) AS v(group_code, code, name, lookup_table, data_type, operator_type, display_order)
|
||||||
|
JOIN masters_rule_engine.tbl_condition_groups g ON g.code = v.group_code
|
||||||
|
ON CONFLICT (code) DO UPDATE SET
|
||||||
|
name = EXCLUDED.name,
|
||||||
|
"lookupTable" = EXCLUDED."lookupTable",
|
||||||
|
"dataType" = EXCLUDED."dataType",
|
||||||
|
"operatorType" = EXCLUDED."operatorType",
|
||||||
|
"displayOrder" = EXCLUDED."displayOrder";
|
||||||
|
|
||||||
|
-- 38. Baggage Types
|
||||||
|
INSERT INTO masters_lookup.tbl_baggage_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Checked Bag', 'checked-bag'),
|
||||||
|
('Cabin Bag', 'cabin-bag'),
|
||||||
|
('Oversized Baggage', 'oversized-baggage'),
|
||||||
|
('Sports Equipment', 'sports-equipment'),
|
||||||
|
('Special Baggage', 'special-baggage')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_baggage_types WHERE masters_lookup.tbl_baggage_types.value = t.value);
|
||||||
|
|
||||||
|
-- 39. Compensation Rules
|
||||||
|
INSERT INTO masters_lookup.tbl_compensation_rules (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('EU261', 'eu261'),
|
||||||
|
('UK261', 'uk261'),
|
||||||
|
('APPR', 'appr'),
|
||||||
|
('DGCA', 'dgca'),
|
||||||
|
('DOT', 'dot'),
|
||||||
|
('Airline Policy', 'airline-policy')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_compensation_rules WHERE masters_lookup.tbl_compensation_rules.value = t.value);
|
||||||
|
|
||||||
|
-- 40. Approval Levels
|
||||||
|
INSERT INTO masters_lookup.tbl_approval_levels (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Supervisor', 'supervisor'),
|
||||||
|
('Manager', 'manager'),
|
||||||
|
('Director', 'director')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_approval_levels WHERE masters_lookup.tbl_approval_levels.value = t.value);
|
||||||
|
|
||||||
|
-- 41. Eligible Fare Types
|
||||||
|
INSERT INTO masters_lookup.tbl_eligible_fare_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Published Fares', 'published-fares'),
|
||||||
|
('Promo Fares', 'promo-fares')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_eligible_fare_types WHERE masters_lookup.tbl_eligible_fare_types.value = t.value);
|
||||||
|
|
||||||
|
-- 42. Applicable Products
|
||||||
|
INSERT INTO masters_lookup.tbl_applicable_products (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Flights', 'flights'),
|
||||||
|
('Ancillary', 'ancillary'),
|
||||||
|
('Lounge', 'lounge')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_applicable_products WHERE masters_lookup.tbl_applicable_products.value = t.value);
|
||||||
|
|
||||||
|
-- 43. Meal Types
|
||||||
|
INSERT INTO masters_lookup.tbl_meal_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Breakfast', 'breakfast'),
|
||||||
|
('Lunch', 'lunch'),
|
||||||
|
('Dinner', 'dinner'),
|
||||||
|
('Snack', 'snack'),
|
||||||
|
('Any', 'any')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_meal_types WHERE masters_lookup.tbl_meal_types.value = t.value);
|
||||||
|
|
||||||
|
-- 44. Airport Restrictions
|
||||||
|
INSERT INTO masters_lookup.tbl_airport_restrictions (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Departure', 'departure'),
|
||||||
|
('Transit', 'transit'),
|
||||||
|
('Arrival', 'arrival'),
|
||||||
|
('Any Airport', 'any-airport')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_airport_restrictions WHERE masters_lookup.tbl_airport_restrictions.value = t.value);
|
||||||
|
|
||||||
|
-- 45. Destination Types
|
||||||
|
INSERT INTO masters_lookup.tbl_destination_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Home', 'home'),
|
||||||
|
('Hotel', 'hotel'),
|
||||||
|
('Airport', 'airport'),
|
||||||
|
('City Center', 'city-center')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_destination_types WHERE masters_lookup.tbl_destination_types.value = t.value);
|
||||||
|
|
||||||
|
-- 46. Vehicle Categories
|
||||||
|
INSERT INTO masters_lookup.tbl_vehicle_categories (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Executive Sedan', 'executive-sedan'),
|
||||||
|
('Luxury SUV', 'luxury-suv'),
|
||||||
|
('Premium Van', 'premium-van')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_vehicle_categories WHERE masters_lookup.tbl_vehicle_categories.value = t.value);
|
||||||
|
|
||||||
|
-- 47. Cabin Preferences
|
||||||
|
INSERT INTO masters_lookup.tbl_cabin_preferences (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Same Cabin', 'same-cabin'),
|
||||||
|
('Upgrade if Available', 'upgrade-if-available'),
|
||||||
|
('Lowest Available', 'lowest-available')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_cabin_preferences WHERE masters_lookup.tbl_cabin_preferences.value = t.value);
|
||||||
|
|
||||||
|
-- 48. Airline Preferences
|
||||||
|
INSERT INTO masters_lookup.tbl_airline_preferences (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Same Airline', 'same-airline'),
|
||||||
|
('Alliance Airline', 'alliance-airline'),
|
||||||
|
('Any Partner', 'any-partner')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_airline_preferences WHERE masters_lookup.tbl_airline_preferences.value = t.value);
|
||||||
|
|
||||||
|
-- 49. Meal Categories
|
||||||
|
INSERT INTO masters_lookup.tbl_meal_categories (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Vegetarian', 'vegetarian'),
|
||||||
|
('Non-Vegetarian', 'non-vegetarian'),
|
||||||
|
('Vegan', 'vegan'),
|
||||||
|
('Child Meal', 'child-meal')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_meal_categories WHERE masters_lookup.tbl_meal_categories.value = t.value);
|
||||||
|
|
||||||
|
-- 50. Seat Categories
|
||||||
|
INSERT INTO masters_lookup.tbl_seat_categories (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Standard', 'standard'),
|
||||||
|
('Preferred', 'preferred'),
|
||||||
|
('Exit Row', 'exit-row'),
|
||||||
|
('Extra Legroom', 'extra-legroom')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_seat_categories WHERE masters_lookup.tbl_seat_categories.value = t.value);
|
||||||
|
|
||||||
|
-- 51. Compensation Bases
|
||||||
|
INSERT INTO masters_lookup.tbl_compensation_bases (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Regulatory Rule', 'regulatory-rule'),
|
||||||
|
('Airline Policy', 'airline-policy'),
|
||||||
|
('Percentage Difference', 'percentage-difference')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_compensation_bases WHERE masters_lookup.tbl_compensation_bases.value = t.value);
|
||||||
|
|
||||||
|
-- 52. Tax Types
|
||||||
|
INSERT INTO masters_lookup.tbl_tax_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airport Tax', 'airport-tax'),
|
||||||
|
('Fuel Surcharge', 'fuel-surcharge'),
|
||||||
|
('Government Tax', 'government-tax'),
|
||||||
|
('Service Tax', 'service-tax'),
|
||||||
|
('VAT', 'vat'),
|
||||||
|
('GST', 'gst'),
|
||||||
|
('Airport Development Fee', 'airport-development-fee')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_tax_types WHERE masters_lookup.tbl_tax_types.value = t.value);
|
||||||
|
|
||||||
|
-- 53. Room Types
|
||||||
|
INSERT INTO masters_lookup.tbl_room_types (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Single', 'single'),
|
||||||
|
('Double', 'double'),
|
||||||
|
('Twin', 'twin'),
|
||||||
|
('Family', 'family')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_room_types WHERE masters_lookup.tbl_room_types.value = t.value);
|
||||||
|
|
||||||
|
-- 54. Hotel Tiers
|
||||||
|
|
||||||
|
INSERT INTO masters_lookup.tbl_hotel_tiers (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('3 Star', '3-star'),
|
||||||
|
('4 Star', '4-star'),
|
||||||
|
('5 Star', '5-star')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_hotel_tiers WHERE masters_lookup.tbl_hotel_tiers.value = t.value);
|
||||||
|
|
||||||
|
-- 55. Hotel Categories
|
||||||
|
|
||||||
|
INSERT INTO masters_lookup.tbl_hotel_categories (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airport Hotel', 'airport-hotel'),
|
||||||
|
('Transit Hotel', 'transit-hotel')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_hotel_categories WHERE masters_lookup.tbl_hotel_categories.value = t.value);
|
||||||
|
|
||||||
|
-- 56. Hotel Chains
|
||||||
|
|
||||||
|
INSERT INTO masters_lookup.tbl_hotel_chains (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Hilton', 'hilton'),
|
||||||
|
('Marriott', 'marriott'),
|
||||||
|
('IHG', 'ihg'),
|
||||||
|
('Hyatt', 'hyatt'),
|
||||||
|
('Radisson', 'radisson')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_hotel_chains WHERE masters_lookup.tbl_hotel_chains.value = t.value);
|
||||||
|
|
||||||
|
-- 57. Loyalty Programs
|
||||||
|
INSERT INTO masters_lookup.tbl_loyalty_programs (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('AeroMiles', 'aeromiles'),
|
||||||
|
('SkyRewards', 'skyrewards'),
|
||||||
|
('StarAlliance', 'staralliance')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_loyalty_programs WHERE masters_lookup.tbl_loyalty_programs.value = t.value);
|
||||||
|
|
||||||
|
-- 58. Promotion Codes
|
||||||
|
INSERT INTO masters_lookup.tbl_promotion_codes (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('SUMMER2026', 'summer2026'),
|
||||||
|
('APOLOGY10', 'apology10'),
|
||||||
|
('FESTIVE25', 'festive25')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_promotion_codes WHERE masters_lookup.tbl_promotion_codes.value = t.value);
|
||||||
|
|
||||||
|
-- 59. Goodwill Reasons
|
||||||
|
INSERT INTO masters_lookup.tbl_goodwill_reasons (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Service Failure', 'service-failure'),
|
||||||
|
('Customer Retention', 'customer-retention'),
|
||||||
|
('Operational Delay', 'operational-delay')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_goodwill_reasons WHERE masters_lookup.tbl_goodwill_reasons.value = t.value);
|
||||||
|
|
||||||
|
-- 60. Routes
|
||||||
|
INSERT INTO masters_lookup.tbl_routes (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Airport to City Center', 'airport-city'),
|
||||||
|
('City Center to Airport', 'city-airport'),
|
||||||
|
('Airport to Terminal 2', 'airport-t2')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_routes WHERE masters_lookup.tbl_routes.value = t.value);
|
||||||
|
|
||||||
|
-- 61. Refund Components
|
||||||
|
INSERT INTO masters_lookup.tbl_refund_components (label, value, "isActive")
|
||||||
|
SELECT label, value, true FROM (VALUES
|
||||||
|
('Base Fare', 'base-fare'),
|
||||||
|
('Taxes', 'taxes'),
|
||||||
|
('Ancillary', 'ancillary'),
|
||||||
|
('Seat Fee', 'seat-fee'),
|
||||||
|
('Baggage Fee', 'baggage-fee'),
|
||||||
|
('Service Fee', 'service-fee')
|
||||||
|
) AS t(label, value)
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM masters_lookup.tbl_refund_components WHERE masters_lookup.tbl_refund_components.value = t.value);
|
||||||
Generated
+548
-116
File diff suppressed because it is too large
Load Diff
+19
-9
@@ -6,19 +6,25 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nest build",
|
"dev": "cross-env NODE_ENV=dev nest start",
|
||||||
"dev": "nest start --watch",
|
"uat": "cross-env NODE_ENV=uat nest start",
|
||||||
|
"local": "cross-env NODE_ENV=local nest start",
|
||||||
|
"seed:dev": "cross-env NODE_ENV=dev ts-node -r tsconfig-paths/register scripts/seed-master-data.ts",
|
||||||
|
"seed:local": "cross-env NODE_ENV=local ts-node -r tsconfig-paths/register scripts/seed-master-data.ts",
|
||||||
|
"seed:uat": "cross-env NODE_ENV=uat ts-node -r tsconfig-paths/register scripts/seed-master-data.ts",
|
||||||
|
"seed:test": "cross-env NODE_ENV=test ts-node -r tsconfig-paths/register scripts/seed-master-data.ts",
|
||||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
"start": "nest start",
|
"start": "nest start",
|
||||||
"start:dev": "nest start --watch",
|
"start:dev": "cross-env NODE_ENV=dev nest start --watch",
|
||||||
|
"start:uat": "cross-env NODE_ENV=uat nest start --watch",
|
||||||
|
"start:local": "cross-env NODE_ENV=local nest start --watch",
|
||||||
"start:debug": "nest start --debug --watch",
|
"start:debug": "nest start --debug --watch",
|
||||||
"start:prod": "node dist/main",
|
"start:prod": "node dist/main",
|
||||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
"test": "jest",
|
"test": "cross-env NODE_ENV=test nest start",
|
||||||
"test:watch": "jest --watch",
|
"test:cov": "cross-env NODE_ENV=test jest --coverage",
|
||||||
"test:cov": "jest --coverage",
|
"test:debug": "cross-env NODE_ENV=test node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:e2e": "cross-env NODE_ENV=test jest --config ./test/jest-e2e.json"
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/common": "^11.0.1",
|
"@nestjs/common": "^11.0.1",
|
||||||
@@ -26,10 +32,13 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
"@nestjs/swagger": "^11.2.0",
|
"@nestjs/swagger": "^11.2.0",
|
||||||
|
"@nestjs/typeorm": "^11.0.3",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
|
"pg": "^8.22.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1",
|
||||||
|
"typeorm": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
@@ -41,6 +50,7 @@
|
|||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/node": "^24.0.0",
|
"@types/node": "^24.0.0",
|
||||||
"@types/supertest": "^7.0.0",
|
"@types/supertest": "^7.0.0",
|
||||||
|
"cross-env": "^10.1.0",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"eslint-plugin-prettier": "^5.2.2",
|
"eslint-plugin-prettier": "^5.2.2",
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { AppModule } from '../src/app.module';
|
||||||
|
import { MasterDataService } from '../src/modules/master-data/master-data.service';
|
||||||
|
import { TenantService } from '../src/modules/tenant/tenant.service';
|
||||||
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
const logger = new Logger('SeedMasterData');
|
||||||
|
logger.log('Starting seed script (tenants + master data)...');
|
||||||
|
|
||||||
|
const app = await NestFactory.createApplicationContext(AppModule);
|
||||||
|
|
||||||
|
const tenantService = app.get(TenantService);
|
||||||
|
const masterDataService = app.get(MasterDataService);
|
||||||
|
|
||||||
|
const tenants = await tenantService.seedDemoTenants();
|
||||||
|
logger.log(`Seeded ${tenants.length} demo tenant(s)`);
|
||||||
|
logger.log('Master data ready (common across all tenants).');
|
||||||
|
|
||||||
|
logger.log('Seeding complete. Exiting...');
|
||||||
|
|
||||||
|
await app.close();
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap().catch((err) => {
|
||||||
|
console.error('Failed to run seed script:', err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
+38
-5
@@ -1,13 +1,46 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||||
|
import { APP_INTERCEPTOR } from '@nestjs/core';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { DatabaseModule } from './database/database.module';
|
||||||
import { HealthModule } from './modules/health/health.module';
|
import { HealthModule } from './modules/health/health.module';
|
||||||
import { DisruptionModule } from './modules/disruption/disruption.module';
|
import { MasterDataModule } from './modules/master-data/master-data.module';
|
||||||
|
import { CohortModule } from './modules/cohort/cohort.module';
|
||||||
|
import { TenantModule } from './modules/tenant/tenant.module';
|
||||||
|
import { TenantMiddleware } from './common/tenant/tenant.middleware';
|
||||||
|
import { PolicyEngineModule } from './modules/policy-engine/policy-engine.module';
|
||||||
|
import { RecoveryIncidentModule } from './modules/recovery-incident/recovery-incident.module';
|
||||||
|
import { AuditLogModule } from './modules/audit-log/audit-log.module';
|
||||||
|
import { DashboardModule } from './modules/dashboard/dashboard.module';
|
||||||
|
import { AuditInterceptor } from './common/interceptors/audit.interceptor';
|
||||||
|
|
||||||
|
const env = process.env.NODE_ENV;
|
||||||
|
const envFilePath = env ? [`.env.${env}`, '.env.local', '.env'] : ['.env.local', '.env'];
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({ isGlobal: true }),
|
ConfigModule.forRoot({
|
||||||
|
isGlobal: true,
|
||||||
|
envFilePath,
|
||||||
|
}),
|
||||||
|
DatabaseModule,
|
||||||
HealthModule,
|
HealthModule,
|
||||||
DisruptionModule,
|
TenantModule,
|
||||||
|
MasterDataModule,
|
||||||
|
CohortModule,
|
||||||
|
PolicyEngineModule,
|
||||||
|
RecoveryIncidentModule,
|
||||||
|
AuditLogModule,
|
||||||
|
DashboardModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: APP_INTERCEPTOR,
|
||||||
|
useClass: AuditInterceptor,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule implements NestModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer.apply(TenantMiddleware).forRoutes('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Column, Index, JoinColumn, ManyToOne } from 'typeorm';
|
||||||
|
import { Tenant } from '../../modules/tenant/tenant.entity';
|
||||||
|
|
||||||
|
export abstract class TenantOwnedEntity {
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
@Index()
|
||||||
|
tenantId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Tenant, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'tenantId' })
|
||||||
|
tenant!: Tenant;
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
CallHandler,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
NestInterceptor,
|
||||||
|
Logger,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { tap } from 'rxjs/operators';
|
||||||
|
import { Request } from 'express';
|
||||||
|
import { AuditLogService } from '../../modules/audit-log/audit-log.service';
|
||||||
|
|
||||||
|
// Methods that mutate data — only these are audited
|
||||||
|
const MUTABLE_METHODS = ['POST', 'PUT', 'PATCH', 'DELETE'];
|
||||||
|
|
||||||
|
// Map: [HTTP method, URL pattern] → { module, action }
|
||||||
|
// The interceptor only handles CREATE (POST) since UPDATE/DELETE
|
||||||
|
// need before-snapshots which are captured directly in each service.
|
||||||
|
const MODULE_MAP: Array<{ pattern: RegExp; module: string }> = [
|
||||||
|
{ pattern: /policy-engine/, module: 'policy-engine' },
|
||||||
|
{ pattern: /recovery-incidents/, module: 'recovery-incident' },
|
||||||
|
{ pattern: /cohort/, module: 'cohort' },
|
||||||
|
{ pattern: /master-data/, module: 'master-data' },
|
||||||
|
];
|
||||||
|
|
||||||
|
function resolveModule(url: string): string {
|
||||||
|
for (const entry of MODULE_MAP) {
|
||||||
|
if (entry.pattern.test(url)) return entry.module;
|
||||||
|
}
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAction(method: string, url: string): string {
|
||||||
|
if (method === 'POST') return 'CREATE';
|
||||||
|
if (method === 'DELETE') return 'DELETE';
|
||||||
|
if (method === 'PATCH' && url.includes('/status')) return 'STATUS_CHANGE';
|
||||||
|
if (method === 'PATCH' || method === 'PUT') return 'UPDATE';
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuditInterceptor implements NestInterceptor {
|
||||||
|
private readonly logger = new Logger(AuditInterceptor.name);
|
||||||
|
|
||||||
|
constructor(private readonly auditLogService: AuditLogService) {}
|
||||||
|
|
||||||
|
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
||||||
|
const req = context.switchToHttp().getRequest<Request>();
|
||||||
|
const { method, ip, headers } = req;
|
||||||
|
const url = req.originalUrl || req.url;
|
||||||
|
|
||||||
|
// Only intercept CREATE (POST) — UPDATE/DELETE handled in services
|
||||||
|
if (!MUTABLE_METHODS.includes(method) || method !== 'POST') {
|
||||||
|
return next.handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
const module = resolveModule(url);
|
||||||
|
const action = resolveAction(method, url);
|
||||||
|
const userAgent = headers['user-agent'] ?? '';
|
||||||
|
const tenantId = (headers['x-tenant-id'] as string) ?? 'unknown';
|
||||||
|
|
||||||
|
this.logger.debug(`Intercepted ${method} ${url} -> Module: ${module}, Action: ${action}`);
|
||||||
|
|
||||||
|
return next.handle().pipe(
|
||||||
|
tap({
|
||||||
|
next: async (responseData: any) => {
|
||||||
|
this.logger.debug(`Writing audit log for ${module} ${action}...`);
|
||||||
|
try {
|
||||||
|
await this.auditLogService.log({
|
||||||
|
module,
|
||||||
|
action,
|
||||||
|
entityId: responseData?.id ?? undefined,
|
||||||
|
entityLabel: responseData?.name ?? responseData?.recoveryCode ?? responseData?.flightNumber ?? undefined,
|
||||||
|
before: undefined, // no before on CREATE
|
||||||
|
after: responseData ?? undefined,
|
||||||
|
performedBy: tenantId,
|
||||||
|
ipAddress: ip,
|
||||||
|
userAgent: String(userAgent),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
// Never let audit failure break the main request
|
||||||
|
this.logger.warn(`Audit log failed for ${method} ${url}: ${err}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { AsyncLocalStorage } from 'async_hooks';
|
||||||
|
|
||||||
|
export interface TenantContextStore {
|
||||||
|
tenantId: string;
|
||||||
|
tenantSlug: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tenantContext = new AsyncLocalStorage<TenantContextStore>();
|
||||||
|
|
||||||
|
export function getTenantId(): string {
|
||||||
|
const tenantId = tenantContext.getStore()?.tenantId;
|
||||||
|
if (!tenantId) {
|
||||||
|
throw new Error('Tenant context is not set');
|
||||||
|
}
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTenantIdOrNull(): string | null {
|
||||||
|
return tenantContext.getStore()?.tenantId ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runWithTenantContext<T>(
|
||||||
|
store: TenantContextStore,
|
||||||
|
fn: () => T,
|
||||||
|
): T {
|
||||||
|
return tenantContext.run(store, fn);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
Injectable,
|
||||||
|
NestMiddleware,
|
||||||
|
NotFoundException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { NextFunction, Request, Response } from 'express';
|
||||||
|
import { TenantService } from '../../modules/tenant/tenant.service';
|
||||||
|
import { tenantContext } from './tenant.context';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TenantMiddleware implements NestMiddleware {
|
||||||
|
constructor(private readonly tenantService: TenantService) {}
|
||||||
|
|
||||||
|
async use(req: Request, res: Response, next: NextFunction) {
|
||||||
|
if (this.isPublicRoute(req.path)) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let tenantHeader = req.headers['x-tenant-id'];
|
||||||
|
if (!tenantHeader || Array.isArray(tenantHeader)) {
|
||||||
|
tenantHeader = 'demo-airline';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tenant = await this.tenantService.resolveTenant(String(tenantHeader));
|
||||||
|
|
||||||
|
return tenantContext.run(
|
||||||
|
{ tenantId: tenant.id, tenantSlug: tenant.slug },
|
||||||
|
() => next(),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof NotFoundException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new BadRequestException('Invalid X-Tenant-Id header');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isPublicRoute(path: string): boolean {
|
||||||
|
return (
|
||||||
|
path === '/api/health' ||
|
||||||
|
path === '/health' ||
|
||||||
|
path.startsWith('/api/tenants') ||
|
||||||
|
path.startsWith('/tenants') ||
|
||||||
|
path.startsWith('/docs') ||
|
||||||
|
path.startsWith('/api-json')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forRootAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: (configService: ConfigService) => ({
|
||||||
|
type: 'postgres',
|
||||||
|
host: configService.get<string>('DB_HOST'),
|
||||||
|
port: Number(configService.get<string>('DB_PORT') ?? 5432),
|
||||||
|
username: configService.get<string>('DB_USER'),
|
||||||
|
password: configService.get<string>('DB_PASSWORD'),
|
||||||
|
database: configService.get<string>('DB_NAME'),
|
||||||
|
synchronize: configService.get<string>('DB_SYNCHRONIZE') === 'true',
|
||||||
|
autoLoadEntities: true,
|
||||||
|
uuidExtension: 'pgcrypto',
|
||||||
|
ssl: configService.get<string>('DB_SSL') === 'true' ? { rejectUnauthorized: false } : false,
|
||||||
|
logging: false,
|
||||||
|
}),
|
||||||
|
dataSourceFactory: async (options) => {
|
||||||
|
if (!options) {
|
||||||
|
throw new Error('Invalid options passed');
|
||||||
|
}
|
||||||
|
const { DataSource } = await import('typeorm');
|
||||||
|
// Initialize without syncing first
|
||||||
|
const dataSource = new DataSource({ ...options, synchronize: false });
|
||||||
|
await dataSource.initialize();
|
||||||
|
|
||||||
|
// Ensure schemas exist safely without dropping user created cohorts or policies
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "tenant";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "masters_rule_engine";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "masters_action_builder";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "masters_lookup";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "cohort";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "policy_engine";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "recovery_incident";`);
|
||||||
|
await dataSource.query(`CREATE SCHEMA IF NOT EXISTS "audit";`);
|
||||||
|
|
||||||
|
// Run synchronization manually if it was enabled
|
||||||
|
if (options.synchronize) {
|
||||||
|
await dataSource.synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataSource;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class DatabaseModule { }
|
||||||
+27
-2
@@ -1,14 +1,25 @@
|
|||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { ValidationPipe } from '@nestjs/common';
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule, {
|
||||||
|
logger: ['log', 'warn', 'error'],
|
||||||
|
});
|
||||||
|
const configService = app.get(ConfigService);
|
||||||
|
const dbHost = configService.get('DB_HOST');
|
||||||
|
const dbPort = configService.get('DB_PORT') ?? '5432';
|
||||||
|
const corsOrigin = configService.get<string>('CORS_ORIGIN') ?? 'http://localhost:5174';
|
||||||
|
const corsOrigins = corsOrigin.split(',').map(origin => origin.trim()).filter(Boolean);
|
||||||
|
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
origin: ['http://localhost:5174'],
|
origin: corsOrigins.length > 1 ? corsOrigins : corsOrigins[0],
|
||||||
credentials: true,
|
credentials: true,
|
||||||
|
allowedHeaders: ['Content-Type', 'Authorization', 'X-Tenant-Id'],
|
||||||
});
|
});
|
||||||
|
|
||||||
app.useGlobalPipes(
|
app.useGlobalPipes(
|
||||||
@@ -18,6 +29,10 @@ async function bootstrap() {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
app.setGlobalPrefix('api');
|
||||||
|
|
||||||
|
const logger = new Logger('Bootstrap');
|
||||||
|
|
||||||
const swaggerConfig = new DocumentBuilder()
|
const swaggerConfig = new DocumentBuilder()
|
||||||
.setTitle('AeroResolve API')
|
.setTitle('AeroResolve API')
|
||||||
.setDescription('Passenger recovery and compensation intelligence platform')
|
.setDescription('Passenger recovery and compensation intelligence platform')
|
||||||
@@ -28,7 +43,17 @@ async function bootstrap() {
|
|||||||
SwaggerModule.setup('docs', app, document);
|
SwaggerModule.setup('docs', app, document);
|
||||||
|
|
||||||
const port = process.env.PORT ?? 3001;
|
const port = process.env.PORT ?? 3001;
|
||||||
|
const environment = process.env.NODE_ENV ?? 'dev';
|
||||||
|
|
||||||
|
logger.log(`🌍 Environment: ${environment}`);
|
||||||
|
|
||||||
await app.listen(port);
|
await app.listen(port);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
logger.log('🚀 AeroResolve API started successfully');
|
||||||
|
logger.log(`🌐 Server : http://localhost:${port}`);
|
||||||
|
logger.log(`📚 Swagger : http://localhost:${port}/docs`);
|
||||||
|
logger.log(`🗄️ Database : PostgreSQL (${dbHost}:${dbPort})`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
Query,
|
||||||
|
NotFoundException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||||
|
import { AuditLogService } from './audit-log.service';
|
||||||
|
|
||||||
|
@ApiTags('Audit Logs')
|
||||||
|
@Controller('audit-logs')
|
||||||
|
export class AuditLogController {
|
||||||
|
constructor(private readonly auditLogService: AuditLogService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@ApiOperation({ summary: 'Get paginated audit logs with optional filters' })
|
||||||
|
findAll(
|
||||||
|
@Query('page') page: string = '1',
|
||||||
|
@Query('limit') limit: string = '20',
|
||||||
|
@Query('module') module?: string,
|
||||||
|
@Query('action') action?: string,
|
||||||
|
@Query('entityId') entityId?: string,
|
||||||
|
@Query('dateFrom') dateFrom?: string,
|
||||||
|
@Query('dateTo') dateTo?: string,
|
||||||
|
) {
|
||||||
|
return this.auditLogService.findAll({
|
||||||
|
page: Number(page),
|
||||||
|
limit: Number(limit),
|
||||||
|
module,
|
||||||
|
action,
|
||||||
|
entityId,
|
||||||
|
dateFrom,
|
||||||
|
dateTo,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
@ApiOperation({ summary: 'Get a single audit log entry by ID' })
|
||||||
|
async findOne(@Param('id') id: string) {
|
||||||
|
const log = await this.auditLogService.findOne(id);
|
||||||
|
if (!log) {
|
||||||
|
throw new NotFoundException(`Audit log entry ${id} not found`);
|
||||||
|
}
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { AuditLog } from './entities/audit-log.entity';
|
||||||
|
import { AuditLogService } from './audit-log.service';
|
||||||
|
import { AuditLogController } from './audit-log.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([AuditLog])],
|
||||||
|
controllers: [AuditLogController],
|
||||||
|
providers: [AuditLogService],
|
||||||
|
exports: [AuditLogService], // exported so other modules can inject it
|
||||||
|
})
|
||||||
|
export class AuditLogModule {}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository, FindOptionsWhere, Between, MoreThanOrEqual, LessThanOrEqual } from 'typeorm';
|
||||||
|
import { AuditLog } from './entities/audit-log.entity';
|
||||||
|
import { CreateAuditLogDto } from './dto/create-audit-log.dto';
|
||||||
|
import { getTenantIdOrNull } from '../../common/tenant/tenant.context';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuditLogService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(AuditLog)
|
||||||
|
private readonly auditLogRepository: Repository<AuditLog>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
// ─── Write a single audit entry ──────────────────────────────────────────
|
||||||
|
// Called directly from services (for UPDATE/DELETE with before snapshots)
|
||||||
|
// and from the HTTP interceptor (for CREATE).
|
||||||
|
async log(dto: CreateAuditLogDto): Promise<void> {
|
||||||
|
const tenantId = getTenantIdOrNull() ?? dto.performedBy ?? 'system';
|
||||||
|
const entry = this.auditLogRepository.create({
|
||||||
|
...dto,
|
||||||
|
tenantId,
|
||||||
|
performedBy: dto.performedBy ?? tenantId,
|
||||||
|
});
|
||||||
|
await this.auditLogRepository.save(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Paginated query with filters ────────────────────────────────────────
|
||||||
|
async findAll(options: {
|
||||||
|
page?: number;
|
||||||
|
limit?: number;
|
||||||
|
module?: string;
|
||||||
|
action?: string;
|
||||||
|
entityId?: string;
|
||||||
|
dateFrom?: string;
|
||||||
|
dateTo?: string;
|
||||||
|
}) {
|
||||||
|
const { page = 1, limit = 20, module, action, entityId, dateFrom, dateTo } = options;
|
||||||
|
const skip = (page - 1) * limit;
|
||||||
|
const tenantId = getTenantIdOrNull();
|
||||||
|
|
||||||
|
const where: FindOptionsWhere<AuditLog> = {};
|
||||||
|
|
||||||
|
if (tenantId) where.tenantId = tenantId;
|
||||||
|
if (module) where.module = module;
|
||||||
|
if (action) where.action = action;
|
||||||
|
if (entityId) where.entityId = entityId;
|
||||||
|
|
||||||
|
if (dateFrom && dateTo) {
|
||||||
|
where.createdAt = Between(new Date(dateFrom), new Date(dateTo)) as any;
|
||||||
|
} else if (dateFrom) {
|
||||||
|
where.createdAt = MoreThanOrEqual(new Date(dateFrom)) as any;
|
||||||
|
} else if (dateTo) {
|
||||||
|
where.createdAt = LessThanOrEqual(new Date(dateTo)) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [data, total] = await this.auditLogRepository.findAndCount({
|
||||||
|
where,
|
||||||
|
skip,
|
||||||
|
take: limit,
|
||||||
|
order: { createdAt: 'DESC' },
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
total,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
totalPages: Math.ceil(total / limit),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Single entry lookup ──────────────────────────────────────────────────
|
||||||
|
async findOne(id: string): Promise<AuditLog | null> {
|
||||||
|
const tenantId = getTenantIdOrNull();
|
||||||
|
const where: FindOptionsWhere<AuditLog> = { id };
|
||||||
|
if (tenantId) where.tenantId = tenantId;
|
||||||
|
return this.auditLogRepository.findOne({ where });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { IsString, IsNotEmpty, IsOptional, IsObject } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateAuditLogDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
module: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
action: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
entityId?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
entityLabel?: string;
|
||||||
|
|
||||||
|
@IsObject()
|
||||||
|
@IsOptional()
|
||||||
|
before?: Record<string, any>;
|
||||||
|
|
||||||
|
@IsObject()
|
||||||
|
@IsOptional()
|
||||||
|
after?: Record<string, any>;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
performedBy?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
ipAddress?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
userAgent?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
Column,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
CreateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_audit_logs', schema: 'audit' })
|
||||||
|
export class AuditLog {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'tenant_id', type: 'varchar', length: 255 })
|
||||||
|
tenantId!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', length: 100 })
|
||||||
|
module!: string; // 'policy-engine' | 'recovery-incident' | 'cohort' | 'master-data'
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', length: 50 })
|
||||||
|
action!: string; // 'CREATE' | 'UPDATE' | 'DELETE' | 'STATUS_CHANGE'
|
||||||
|
|
||||||
|
@Column({ name: 'entity_id', type: 'varchar', length: 255, nullable: true })
|
||||||
|
entityId?: string;
|
||||||
|
|
||||||
|
@Column({ name: 'entity_label', type: 'varchar', length: 255, nullable: true })
|
||||||
|
entityLabel?: string; // human-readable name (policy name, flight #, etc.)
|
||||||
|
|
||||||
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
|
before?: Record<string, any>; // snapshot before change (null for CREATE)
|
||||||
|
|
||||||
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
|
after?: Record<string, any>; // snapshot after change (null for DELETE)
|
||||||
|
|
||||||
|
@Column({ name: 'performed_by', type: 'varchar', length: 255, nullable: true })
|
||||||
|
performedBy?: string; // tenantId for now; will be userId when auth is added
|
||||||
|
|
||||||
|
@Column({ name: 'ip_address', type: 'varchar', length: 50, nullable: true })
|
||||||
|
ipAddress?: string;
|
||||||
|
|
||||||
|
@Column({ name: 'user_agent', type: 'text', nullable: true })
|
||||||
|
userAgent?: string;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'created_at' })
|
||||||
|
createdAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Controller, Get, Post, Body, Param, Put, Delete, Patch, Query } from '@nestjs/common';
|
||||||
|
import { CohortService } from './cohort.service';
|
||||||
|
import { CreateCohortDto } from './dto/create-cohort.dto';
|
||||||
|
import { UpdateCohortDto } from './dto/update-cohort.dto';
|
||||||
|
|
||||||
|
@Controller('cohorts')
|
||||||
|
export class CohortController {
|
||||||
|
constructor(private readonly cohortService: CohortService) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
async create(@Body() createCohortDto: CreateCohortDto) {
|
||||||
|
return this.cohortService.create(createCohortDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
async findAll(
|
||||||
|
@Query('page') page: string = '1',
|
||||||
|
@Query('limit') limit: string = '10',
|
||||||
|
) {
|
||||||
|
return this.cohortService.findAll(Number(page), Number(limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
async findOne(@Param('id') id: string) {
|
||||||
|
return this.cohortService.findOne(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
async update(@Param('id') id: string, @Body() updateCohortDto: UpdateCohortDto) {
|
||||||
|
return this.cohortService.update(id, updateCohortDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(':id/status')
|
||||||
|
async updateStatus(@Param('id') id: string, @Body('status') status: string) {
|
||||||
|
return this.cohortService.updateStatus(id, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
async remove(@Param('id') id: string) {
|
||||||
|
return this.cohortService.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToMany, JoinTable } from 'typeorm';
|
||||||
|
import { TenantOwnedEntity } from '../../common/entities/tenant-owned.entity';
|
||||||
|
import { CabinClass } from '../master-data/entities/cabin-class.entity';
|
||||||
|
import { PassengerType } from '../master-data/entities/passenger-type.entity';
|
||||||
|
import { AncillaryPurchase } from '../master-data/entities/ancillary-purchase.entity';
|
||||||
|
import { MembershipTier } from '../master-data/entities/membership-tier.entity';
|
||||||
|
import { RevenueSegment } from '../master-data/entities/revenue-segment.entity';
|
||||||
|
import { Region } from '../master-data/entities/region.entity';
|
||||||
|
import { TripPurpose } from '../master-data/entities/trip-purpose.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_cohorts', schema: 'cohort' })
|
||||||
|
export class Cohort extends TenantOwnedEntity {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
scopeType!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
description!: string;
|
||||||
|
|
||||||
|
@Column({ default: 'Draft' })
|
||||||
|
status!: string; // Draft, Active, Inactive
|
||||||
|
|
||||||
|
// Passenger Attributes
|
||||||
|
@ManyToMany(() => CabinClass)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_cabin_classes',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'cabinClassId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
cabinClasses!: CabinClass[];
|
||||||
|
|
||||||
|
@ManyToMany(() => PassengerType)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_passenger_types',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'passengerTypeId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
passengerTypes!: PassengerType[];
|
||||||
|
|
||||||
|
@ManyToMany(() => AncillaryPurchase)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_ancillary_purchases',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'ancillaryPurchaseId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
ancillaryPurchases!: AncillaryPurchase[];
|
||||||
|
|
||||||
|
// Customer Value
|
||||||
|
@ManyToMany(() => MembershipTier)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_loyalty_tiers',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'membershipTierId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
loyaltyTiers!: MembershipTier[];
|
||||||
|
|
||||||
|
@ManyToMany(() => RevenueSegment)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_revenue_segments',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'revenueSegmentId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
revenueSegments!: RevenueSegment[];
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: ['Any', 'Yes(VIP/Strategic)', 'No'],
|
||||||
|
default: 'Any'
|
||||||
|
})
|
||||||
|
highValuePassenger!: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: ['Domestic Only', 'International Only', 'Both (All)'],
|
||||||
|
nullable: true
|
||||||
|
})
|
||||||
|
flightType!: string;
|
||||||
|
|
||||||
|
@ManyToMany(() => Region)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_regions',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'regionId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
regions!: Region[];
|
||||||
|
|
||||||
|
@ManyToMany(() => TripPurpose)
|
||||||
|
@JoinTable({
|
||||||
|
name: 'tbl_cohort_trip_purposes',
|
||||||
|
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
|
||||||
|
inverseJoinColumn: { name: 'tripPurposeId', referencedColumnName: 'id' }
|
||||||
|
})
|
||||||
|
tripPurposes!: TripPurpose[];
|
||||||
|
|
||||||
|
@Column('simple-array', { nullable: true })
|
||||||
|
originAirport!: string[];
|
||||||
|
|
||||||
|
@Column('simple-array', { nullable: true })
|
||||||
|
destinationAirport!: string[];
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { CohortController } from './cohort.controller';
|
||||||
|
import { CohortService } from './cohort.service';
|
||||||
|
import { Cohort } from './cohort.entity';
|
||||||
|
import { AuditLogModule } from '../audit-log/audit-log.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([Cohort]), AuditLogModule],
|
||||||
|
controllers: [CohortController],
|
||||||
|
providers: [CohortService],
|
||||||
|
exports: [CohortService],
|
||||||
|
})
|
||||||
|
export class CohortModule {}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository, DeepPartial } from 'typeorm';
|
||||||
|
import { getTenantId } from '../../common/tenant/tenant.context';
|
||||||
|
import { Cohort } from './cohort.entity';
|
||||||
|
import { CreateCohortDto } from './dto/create-cohort.dto';
|
||||||
|
import { UpdateCohortDto } from './dto/update-cohort.dto';
|
||||||
|
import { AuditLogService } from '../audit-log/audit-log.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CohortService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(Cohort)
|
||||||
|
private readonly cohortRepository: Repository<Cohort>,
|
||||||
|
private readonly auditLogService: AuditLogService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private mapDtoToEntity(dto: CreateCohortDto | UpdateCohortDto) {
|
||||||
|
const {
|
||||||
|
cabinClassIds,
|
||||||
|
passengerTypeIds,
|
||||||
|
ancillaryPurchaseIds,
|
||||||
|
loyaltyTierIds,
|
||||||
|
revenueSegmentIds,
|
||||||
|
regionIds,
|
||||||
|
tripPurposeIds,
|
||||||
|
originAirports,
|
||||||
|
destinationAirports,
|
||||||
|
...rest
|
||||||
|
} = dto;
|
||||||
|
|
||||||
|
const mapping: any = { ...rest };
|
||||||
|
|
||||||
|
if (cabinClassIds) mapping.cabinClasses = cabinClassIds.map(id => ({ id }));
|
||||||
|
if (passengerTypeIds) mapping.passengerTypes = passengerTypeIds.map(id => ({ id }));
|
||||||
|
if (ancillaryPurchaseIds) mapping.ancillaryPurchases = ancillaryPurchaseIds.map(id => ({ id }));
|
||||||
|
if (loyaltyTierIds) mapping.loyaltyTiers = loyaltyTierIds.map(id => ({ id }));
|
||||||
|
if (revenueSegmentIds) mapping.revenueSegments = revenueSegmentIds.map(id => ({ id }));
|
||||||
|
if (regionIds) mapping.regions = regionIds.map(id => ({ id }));
|
||||||
|
if (tripPurposeIds) mapping.tripPurposes = tripPurposeIds.map(id => ({ id }));
|
||||||
|
if (originAirports !== undefined) mapping.originAirport = originAirports;
|
||||||
|
if (destinationAirports !== undefined) mapping.destinationAirport = destinationAirports;
|
||||||
|
|
||||||
|
return mapping as DeepPartial<Cohort>;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRelations() {
|
||||||
|
return {
|
||||||
|
cabinClasses: true,
|
||||||
|
passengerTypes: true,
|
||||||
|
ancillaryPurchases: true,
|
||||||
|
loyaltyTiers: true,
|
||||||
|
revenueSegments: true,
|
||||||
|
regions: true,
|
||||||
|
tripPurposes: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(createCohortDto: CreateCohortDto): Promise<Cohort> {
|
||||||
|
const mappedData = this.mapDtoToEntity(createCohortDto);
|
||||||
|
const cohort = this.cohortRepository.create({
|
||||||
|
...mappedData,
|
||||||
|
tenantId: getTenantId(),
|
||||||
|
});
|
||||||
|
return this.cohortRepository.save(cohort);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(page: number = 1, limit: number = 10) {
|
||||||
|
const skip = (page - 1) * limit;
|
||||||
|
const tenantId = getTenantId();
|
||||||
|
const [data, total] = await this.cohortRepository.findAndCount({
|
||||||
|
where: { tenantId },
|
||||||
|
skip,
|
||||||
|
take: limit,
|
||||||
|
order: { createdAt: 'DESC' },
|
||||||
|
relations: this.getRelations(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
total,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
totalPages: Math.ceil(total / limit),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne(id: string): Promise<Cohort> {
|
||||||
|
const cohort = await this.cohortRepository.findOne({
|
||||||
|
where: { id, tenantId: getTenantId() },
|
||||||
|
relations: this.getRelations(),
|
||||||
|
});
|
||||||
|
if (!cohort) {
|
||||||
|
throw new NotFoundException(`Cohort with ID ${id} not found`);
|
||||||
|
}
|
||||||
|
return cohort;
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, updateCohortDto: UpdateCohortDto): Promise<Cohort> {
|
||||||
|
const cohort = await this.findOne(id);
|
||||||
|
const beforeSnapshot = { ...cohort };
|
||||||
|
const mappedData = this.mapDtoToEntity(updateCohortDto);
|
||||||
|
Object.assign(cohort, mappedData);
|
||||||
|
const after = await this.cohortRepository.save(cohort);
|
||||||
|
|
||||||
|
await this.auditLogService.log({
|
||||||
|
module: 'cohort',
|
||||||
|
action: 'UPDATE',
|
||||||
|
entityId: id,
|
||||||
|
entityLabel: cohort.name,
|
||||||
|
before: beforeSnapshot,
|
||||||
|
after: { ...after },
|
||||||
|
performedBy: getTenantId(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return after;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateStatus(id: string, status: string): Promise<Cohort> {
|
||||||
|
const cohort = await this.findOne(id);
|
||||||
|
const beforeStatus = cohort.status;
|
||||||
|
cohort.status = status;
|
||||||
|
const after = await this.cohortRepository.save(cohort);
|
||||||
|
|
||||||
|
await this.auditLogService.log({
|
||||||
|
module: 'cohort',
|
||||||
|
action: 'STATUS_CHANGE',
|
||||||
|
entityId: id,
|
||||||
|
entityLabel: cohort.name,
|
||||||
|
before: { status: beforeStatus },
|
||||||
|
after: { status },
|
||||||
|
performedBy: getTenantId(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return after;
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: string): Promise<void> {
|
||||||
|
const cohort = await this.findOne(id);
|
||||||
|
const beforeSnapshot = { ...cohort };
|
||||||
|
await this.cohortRepository.remove(cohort);
|
||||||
|
|
||||||
|
await this.auditLogService.log({
|
||||||
|
module: 'cohort',
|
||||||
|
action: 'DELETE',
|
||||||
|
entityId: id,
|
||||||
|
entityLabel: beforeSnapshot.name,
|
||||||
|
before: beforeSnapshot,
|
||||||
|
after: undefined,
|
||||||
|
performedBy: getTenantId(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { IsString, IsNotEmpty, IsOptional, IsArray } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateCohortDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
scopeType?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
status?: string;
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
cabinClassIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
passengerTypeIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
ancillaryPurchaseIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
loyaltyTierIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
revenueSegmentIds?: string[];
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
highValuePassenger?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
flightType?: string;
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
regionIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
tripPurposeIds?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
originAirports?: string[];
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@IsOptional()
|
||||||
|
destinationAirports?: string[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateCohortDto } from './create-cohort.dto';
|
||||||
|
|
||||||
|
export class UpdateCohortDto extends PartialType(CreateCohortDto) {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
||||||
|
import { DashboardService } from './dashboard.service';
|
||||||
|
|
||||||
|
@ApiTags('Dashboard')
|
||||||
|
@Controller('dashboard')
|
||||||
|
export class DashboardController {
|
||||||
|
constructor(private readonly dashboardService: DashboardService) {}
|
||||||
|
|
||||||
|
@Get('metrics')
|
||||||
|
@ApiOperation({ summary: 'Get dashboard summary metrics' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Return 5 aggregated metric cards for dashboard' })
|
||||||
|
getMetrics() {
|
||||||
|
return this.dashboardService.getMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('exposure')
|
||||||
|
@ApiOperation({ summary: 'Get refund and compensation exposure data' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Return exposure category metrics' })
|
||||||
|
getExposure() {
|
||||||
|
return this.dashboardService.getExposure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('disruption-mix')
|
||||||
|
@ApiOperation({ summary: 'Get disruption mix breakdown' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Return disruption mix category breakdown' })
|
||||||
|
getDisruptionMix() {
|
||||||
|
return this.dashboardService.getDisruptionMix();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('recent-incidents')
|
||||||
|
@ApiOperation({ summary: 'Get recent recovery incidents for dashboard' })
|
||||||
|
@ApiResponse({ status: 200, description: 'Return recent incident rows' })
|
||||||
|
getRecentIncidents() {
|
||||||
|
return this.dashboardService.getRecentIncidents();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { DashboardController } from './dashboard.controller';
|
||||||
|
import { DashboardService } from './dashboard.service';
|
||||||
|
import { RecoveryIncident } from '../recovery-incident/entities/recovery-incident.entity';
|
||||||
|
import { Policy } from '../policy-engine/entities/policy.entity';
|
||||||
|
import { Cohort } from '../cohort/cohort.entity';
|
||||||
|
import { AuditLog } from '../audit-log/entities/audit-log.entity';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([RecoveryIncident, Policy, Cohort, AuditLog]),
|
||||||
|
],
|
||||||
|
controllers: [DashboardController],
|
||||||
|
providers: [DashboardService],
|
||||||
|
exports: [DashboardService],
|
||||||
|
})
|
||||||
|
export class DashboardModule {}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { RecoveryIncident } from '../recovery-incident/entities/recovery-incident.entity';
|
||||||
|
import { Policy } from '../policy-engine/entities/policy.entity';
|
||||||
|
import { PolicyStatus } from '../policy-engine/entities/policy.enums';
|
||||||
|
import { Cohort } from '../cohort/cohort.entity';
|
||||||
|
import { AuditLog } from '../audit-log/entities/audit-log.entity';
|
||||||
|
import { getTenantId } from '../../common/tenant/tenant.context';
|
||||||
|
|
||||||
|
export interface DashboardMetricResponse {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
value: string;
|
||||||
|
trend: string;
|
||||||
|
isPositive: boolean;
|
||||||
|
sparklineData: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExposureChartItemResponse {
|
||||||
|
category: string;
|
||||||
|
amount: number;
|
||||||
|
displayAmount: string;
|
||||||
|
color: string;
|
||||||
|
views?: string;
|
||||||
|
date?: string;
|
||||||
|
hasTooltip?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DisruptionMixItemResponse {
|
||||||
|
label: string;
|
||||||
|
percentage: number;
|
||||||
|
value: string;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecentIncidentResponse {
|
||||||
|
id: string;
|
||||||
|
recoveryId: string;
|
||||||
|
passengerName: string;
|
||||||
|
pnr: string;
|
||||||
|
flightNumber: string;
|
||||||
|
category: string;
|
||||||
|
status: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DashboardService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(RecoveryIncident)
|
||||||
|
private readonly incidentRepo: Repository<RecoveryIncident>,
|
||||||
|
@InjectRepository(Policy)
|
||||||
|
private readonly policyRepo: Repository<Policy>,
|
||||||
|
@InjectRepository(Cohort)
|
||||||
|
private readonly cohortRepo: Repository<Cohort>,
|
||||||
|
@InjectRepository(AuditLog)
|
||||||
|
private readonly auditLogRepo: Repository<AuditLog>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private parseAmount(valStr?: string): number {
|
||||||
|
if (!valStr) return 0;
|
||||||
|
const num = parseFloat(valStr.replace(/[^0-9.]/g, ''));
|
||||||
|
return isNaN(num) ? 0 : num;
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatCurrency(amount: number): string {
|
||||||
|
if (amount >= 1000000) {
|
||||||
|
return `$${(amount / 1000000).toFixed(1)}m`;
|
||||||
|
}
|
||||||
|
if (amount >= 1000) {
|
||||||
|
return `$${Math.round(amount / 1000)}k`;
|
||||||
|
}
|
||||||
|
return `$${amount.toLocaleString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMetrics(): Promise<DashboardMetricResponse[]> {
|
||||||
|
const tenantId = getTenantId();
|
||||||
|
|
||||||
|
const [incidents, activePoliciesCount, auditLogsCount] = await Promise.all([
|
||||||
|
this.incidentRepo.find({ where: { tenantId } }),
|
||||||
|
this.policyRepo.count({ where: { tenantId, status: PolicyStatus.ACTIVE } }),
|
||||||
|
this.auditLogRepo.count({ where: { tenantId } }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let totalExposure = 0;
|
||||||
|
let baggageClaimsCount = 0;
|
||||||
|
let ancillaryRefundsCount = 0;
|
||||||
|
|
||||||
|
incidents.forEach((inc) => {
|
||||||
|
totalExposure += this.parseAmount(inc.value);
|
||||||
|
const cat = (inc.category || '').toLowerCase();
|
||||||
|
if (cat.includes('baggage')) {
|
||||||
|
baggageClaimsCount++;
|
||||||
|
} else if (cat.includes('ancillary')) {
|
||||||
|
ancillaryRefundsCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalSimulationsCount = incidents.length + auditLogsCount;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'total-simulations',
|
||||||
|
title: 'Total Simulations',
|
||||||
|
value: totalSimulationsCount.toLocaleString(),
|
||||||
|
trend: '+18%',
|
||||||
|
isPositive: true,
|
||||||
|
sparklineData: [20, 24, 22, 28, 25, 32, 30, 38],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'refund-exposure',
|
||||||
|
title: 'Refund Exposure',
|
||||||
|
value: this.formatCurrency(totalExposure),
|
||||||
|
trend: '+12%',
|
||||||
|
isPositive: true,
|
||||||
|
sparklineData: [15, 18, 16, 22, 24, 21, 29, 34],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'active-policies',
|
||||||
|
title: 'Active Policies',
|
||||||
|
value: activePoliciesCount.toLocaleString(),
|
||||||
|
trend: 'Stable',
|
||||||
|
isPositive: true,
|
||||||
|
sparklineData: [25, 26, 25, 27, 26, 28, 27, 29],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'baggage-claims',
|
||||||
|
title: 'Baggage Claims',
|
||||||
|
value: baggageClaimsCount.toLocaleString(),
|
||||||
|
trend: '+5%',
|
||||||
|
isPositive: true,
|
||||||
|
sparklineData: [10, 14, 18, 15, 22, 20, 25, 30],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ancillary-refunds',
|
||||||
|
title: 'Ancillary Refunds',
|
||||||
|
value: ancillaryRefundsCount.toLocaleString(),
|
||||||
|
trend: '+22%',
|
||||||
|
isPositive: true,
|
||||||
|
sparklineData: [12, 16, 15, 24, 20, 28, 32, 40],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getExposure(): Promise<ExposureChartItemResponse[]> {
|
||||||
|
const tenantId = getTenantId();
|
||||||
|
const incidents = await this.incidentRepo.find({ where: { tenantId } });
|
||||||
|
|
||||||
|
const categories: Record<string, { amount: number; color: string }> = {
|
||||||
|
'Flight Ops': { amount: 0, color: '#146C43' },
|
||||||
|
'Baggage': { amount: 0, color: '#23865D' },
|
||||||
|
'Ancillary': { amount: 0, color: '#5F9E7F' },
|
||||||
|
'Downgrade': { amount: 0, color: '#7BAA92' },
|
||||||
|
};
|
||||||
|
|
||||||
|
incidents.forEach((inc) => {
|
||||||
|
const val = this.parseAmount(inc.value);
|
||||||
|
const cat = inc.category || 'Flight Ops';
|
||||||
|
if (categories[cat]) {
|
||||||
|
categories[cat].amount += val;
|
||||||
|
} else {
|
||||||
|
categories['Flight Ops'].amount += val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const nowStr = new Date().toLocaleDateString('en-US', {
|
||||||
|
weekday: 'long',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.entries(categories).map(([catName, item]) => ({
|
||||||
|
category: catName,
|
||||||
|
amount: item.amount,
|
||||||
|
displayAmount: this.formatCurrency(item.amount),
|
||||||
|
color: item.color,
|
||||||
|
views: `${incidents.filter((i) => (i.category || 'Flight Ops') === catName).length} cases`,
|
||||||
|
date: nowStr,
|
||||||
|
hasTooltip: catName === 'Baggage',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDisruptionMix(): Promise<DisruptionMixItemResponse[]> {
|
||||||
|
const tenantId = getTenantId();
|
||||||
|
const incidents = await this.incidentRepo.find({ where: { tenantId } });
|
||||||
|
|
||||||
|
const categories: Record<string, { count: number; valueSum: number; color: string }> = {
|
||||||
|
'Flight Ops': { count: 0, valueSum: 0, color: '#146C43' },
|
||||||
|
'Baggage': { count: 0, valueSum: 0, color: '#23865D' },
|
||||||
|
'Ancillary': { count: 0, valueSum: 0, color: '#5F9E7F' },
|
||||||
|
'Downgrade': { count: 0, valueSum: 0, color: '#7BAA92' },
|
||||||
|
};
|
||||||
|
|
||||||
|
let totalSum = 0;
|
||||||
|
incidents.forEach((inc) => {
|
||||||
|
const val = this.parseAmount(inc.value);
|
||||||
|
const cat = inc.category || 'Flight Ops';
|
||||||
|
totalSum += val;
|
||||||
|
if (categories[cat]) {
|
||||||
|
categories[cat].count += 1;
|
||||||
|
categories[cat].valueSum += val;
|
||||||
|
} else {
|
||||||
|
categories['Flight Ops'].count += 1;
|
||||||
|
categories['Flight Ops'].valueSum += val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalCount = incidents.length || 1;
|
||||||
|
|
||||||
|
return Object.entries(categories).map(([label, item]) => {
|
||||||
|
const percentage = totalSum > 0
|
||||||
|
? Math.round((item.valueSum / totalSum) * 100)
|
||||||
|
: Math.round((item.count / totalCount) * 100);
|
||||||
|
|
||||||
|
return {
|
||||||
|
label,
|
||||||
|
percentage,
|
||||||
|
value: this.formatCurrency(item.valueSum),
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecentIncidents(): Promise<RecentIncidentResponse[]> {
|
||||||
|
const tenantId = getTenantId();
|
||||||
|
const incidents = await this.incidentRepo.find({
|
||||||
|
where: { tenantId },
|
||||||
|
order: { createdAt: 'DESC' },
|
||||||
|
take: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
return incidents.map((inc) => ({
|
||||||
|
id: inc.id,
|
||||||
|
recoveryId: inc.recoveryCode || inc.id.substring(0, 16),
|
||||||
|
passengerName: inc.passengerName || 'N/A',
|
||||||
|
pnr: inc.pnr || '',
|
||||||
|
flightNumber: inc.flightNumber || 'N/A',
|
||||||
|
category: inc.category || 'General',
|
||||||
|
status: inc.status || 'Active',
|
||||||
|
value: inc.value || '$0',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
const DEMO_DISRUPTION_ID = 'disruption-ek542';
|
|
||||||
|
|
||||||
const baseDisruption: any = {
|
|
||||||
id: DEMO_DISRUPTION_ID,
|
|
||||||
tenantId: 'tenant-demo',
|
|
||||||
flightNumber: 'EK542',
|
|
||||||
route: { origin: 'DXB', destination: 'CDG' },
|
|
||||||
scheduledDeparture: '2026-07-02T08:00:00.000Z',
|
|
||||||
estimatedDeparture: '2026-07-02T12:00:00.000Z',
|
|
||||||
delayMinutes: 240,
|
|
||||||
type: 'DELAY',
|
|
||||||
status: 'AWAITING_APPROVAL',
|
|
||||||
reason: 'Technical Issue',
|
|
||||||
aircraftType: 'A380-800',
|
|
||||||
airlineResponsible: true,
|
|
||||||
createdAt: '2026-07-02T06:15:00.000Z',
|
|
||||||
updatedAt: '2026-07-02T06:20:00.000Z',
|
|
||||||
};
|
|
||||||
|
|
||||||
const impactSummary: any = {
|
|
||||||
totalPassengers: 150,
|
|
||||||
compensationEligible: 92,
|
|
||||||
connectionsAtRisk: 25,
|
|
||||||
estimatedExposure: 36800,
|
|
||||||
currency: 'EUR',
|
|
||||||
jurisdiction: 'EU261',
|
|
||||||
};
|
|
||||||
|
|
||||||
const passengerSegments: any[] = [
|
|
||||||
{ label: 'Premium / Business', count: 18, percentage: 12 },
|
|
||||||
{ label: 'Frequent Flyers', count: 35, percentage: 23 },
|
|
||||||
{ label: 'Families', count: 20, percentage: 13 },
|
|
||||||
{ label: 'Connecting Pax', count: 25, percentage: 17 },
|
|
||||||
{ label: 'Economy', count: 52, percentage: 35 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const recoveryPlan: any = {
|
|
||||||
id: 'recovery-ek542',
|
|
||||||
disruptionId: DEMO_DISRUPTION_ID,
|
|
||||||
status: 'PENDING_APPROVAL',
|
|
||||||
actions: [
|
|
||||||
{ type: 'HOTEL', description: 'Hotel allocation', quantity: 70, estimatedCost: 14000 },
|
|
||||||
{ type: 'MEAL_VOUCHER', description: 'Meal vouchers', quantity: 150, estimatedCost: 4500 },
|
|
||||||
{ type: 'REBOOKING', description: 'Next available rebooking', quantity: 25, estimatedCost: 0 },
|
|
||||||
{ type: 'LOUNGE', description: 'Lounge access', quantity: 18, estimatedCost: 1800 },
|
|
||||||
{ type: 'GROUND_TRANSPORT', description: 'Ground transport', quantity: 20, estimatedCost: 2200 },
|
|
||||||
],
|
|
||||||
estimatedRecoveryCost: 22500,
|
|
||||||
estimatedExposure: 36800,
|
|
||||||
potentialSavings: 14300,
|
|
||||||
currency: 'EUR',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const demoDisruptionDetail: any = {
|
|
||||||
disruption: baseDisruption,
|
|
||||||
impact: impactSummary,
|
|
||||||
segments: passengerSegments,
|
|
||||||
recoveryPlan,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function cloneDetail(
|
|
||||||
overrides: Partial<any> = {},
|
|
||||||
): any {
|
|
||||||
return {
|
|
||||||
disruption: { ...demoDisruptionDetail.disruption, ...overrides.disruption },
|
|
||||||
impact: { ...demoDisruptionDetail.impact, ...overrides.impact },
|
|
||||||
segments: overrides.segments ?? demoDisruptionDetail.segments,
|
|
||||||
recoveryPlan: overrides.recoveryPlan
|
|
||||||
? { ...demoDisruptionDetail.recoveryPlan!, ...overrides.recoveryPlan }
|
|
||||||
: demoDisruptionDetail.recoveryPlan,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Controller, Get, Param, Post } from '@nestjs/common';
|
|
||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
|
||||||
import { DisruptionService } from './disruption.service';
|
|
||||||
|
|
||||||
@ApiTags('disruptions')
|
|
||||||
@Controller('disruptions')
|
|
||||||
export class DisruptionController {
|
|
||||||
constructor(private readonly disruptionService: DisruptionService) {}
|
|
||||||
|
|
||||||
@Get()
|
|
||||||
@ApiOperation({ summary: 'List active disruptions' })
|
|
||||||
findAll(): any[] {
|
|
||||||
return this.disruptionService.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get(':id')
|
|
||||||
@ApiOperation({ summary: 'Get disruption detail with impact and recovery plan' })
|
|
||||||
findOne(@Param('id') id: string): any {
|
|
||||||
return this.disruptionService.findOne(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Post(':id/approve')
|
|
||||||
@ApiOperation({ summary: 'Approve recovery plan' })
|
|
||||||
approve(@Param('id') id: string): any {
|
|
||||||
return this.disruptionService.approve(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Post(':id/reject')
|
|
||||||
@ApiOperation({ summary: 'Reject recovery plan' })
|
|
||||||
reject(@Param('id') id: string): any {
|
|
||||||
return this.disruptionService.reject(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { DisruptionController } from './disruption.controller';
|
|
||||||
import { DisruptionService } from './disruption.service';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
controllers: [DisruptionController],
|
|
||||||
providers: [DisruptionService],
|
|
||||||
exports: [DisruptionService],
|
|
||||||
})
|
|
||||||
export class DisruptionModule {}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
||||||
import { cloneDetail, demoDisruptionDetail } from './data/demo-disruption';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DisruptionService {
|
|
||||||
private readonly store = new Map<string, any>([
|
|
||||||
[demoDisruptionDetail.disruption.id, cloneDetail()],
|
|
||||||
]);
|
|
||||||
|
|
||||||
findAll(): any[] {
|
|
||||||
return Array.from(this.store.values()).map((item) => item.disruption);
|
|
||||||
}
|
|
||||||
|
|
||||||
findOne(id: string): any {
|
|
||||||
const detail = this.store.get(id);
|
|
||||||
if (!detail) {
|
|
||||||
throw new NotFoundException(`Disruption ${id} not found`);
|
|
||||||
}
|
|
||||||
return cloneDetail(detail);
|
|
||||||
}
|
|
||||||
|
|
||||||
approve(id: string): any {
|
|
||||||
const current = this.findOne(id);
|
|
||||||
const updated = cloneDetail({
|
|
||||||
disruption: {
|
|
||||||
...current.disruption,
|
|
||||||
status: 'COMPLETED',
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
recoveryPlan: {
|
|
||||||
...current.recoveryPlan!,
|
|
||||||
status: 'COMPLETED',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.store.set(id, updated);
|
|
||||||
return cloneDetail(updated);
|
|
||||||
}
|
|
||||||
|
|
||||||
reject(id: string): any {
|
|
||||||
const current = this.findOne(id);
|
|
||||||
const updated = cloneDetail({
|
|
||||||
disruption: {
|
|
||||||
...current.disruption,
|
|
||||||
status: 'REJECTED',
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
recoveryPlan: {
|
|
||||||
...current.recoveryPlan!,
|
|
||||||
status: 'REJECTED',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.store.set(id, updated);
|
|
||||||
return cloneDetail(updated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsString, IsNotEmpty, IsObject, IsOptional, IsNumber, IsBoolean, IsArray, ValidateNested } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
|
||||||
|
export class ActionSubmissionValueDto {
|
||||||
|
@ApiProperty({ description: 'Field Definition ID', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
field_definition_id?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Field Code', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
field_code?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Value index for array inputs', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
value_index?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Selected value ID for dropdowns and lookups', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
selected_value_id?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Text value', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
text_value?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Numeric value', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
number_value?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Boolean value', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
boolean_value?: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Date string (YYYY-MM-DD)', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
date_value?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Time string (HH:MM)', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
time_value?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Timestamp ISO string', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
timestamp_value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActionSubmissionDto {
|
||||||
|
@ApiProperty({ description: 'Category ID', example: 'cat_comp' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
category_id!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Action Type ID', example: 'at_cash_comp' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
action_type_id!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'List of dynamic submission values', required: false, type: [ActionSubmissionValueDto] })
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ActionSubmissionValueDto)
|
||||||
|
values?: ActionSubmissionValueDto[];
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Form submitted dynamic data dictionary (fallback)', required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
data?: Record<string, any>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateActionCategoryDto {
|
||||||
|
@ApiPropertyOptional({ example: 'passenger-compensation', description: 'Unique action category code' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Passenger Compensation', description: 'Display name for the action category' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Actions related to passenger compensation', description: 'Optional description' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 1, description: 'Order used for display sorting' })
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
displayOrder?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: true, description: 'Whether the record is active' })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateActionTypeDto {
|
||||||
|
@ApiPropertyOptional({ example: '00000000-0000-0000-0000-000000000000', description: 'Parent action category id' })
|
||||||
|
@IsUUID()
|
||||||
|
@IsNotEmpty()
|
||||||
|
categoryId: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'voucher-refund', description: 'Unique action type code' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Voucher Refund', description: 'Display name for the action type' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Issue a compensation voucher refund', description: 'Optional description' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 1, description: 'Order used for display sorting' })
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
displayOrder?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: true, description: 'Whether the record is active' })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import {
|
||||||
|
IsString,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsOptional,
|
||||||
|
IsBoolean,
|
||||||
|
IsInt,
|
||||||
|
IsObject,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateFieldDefinitionDto {
|
||||||
|
@ApiProperty({ description: 'Action type ID', example: 'at_cash_comp' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
actionTypeId!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Unique field code within action type', example: 'payout_amount' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
fieldCode!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Human readable field label', example: 'Payout Amount' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
fieldName!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Control field type (textbox, currency, dropdown, etc.)', example: 'currency' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
fieldType!: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Master data code for lookup options (e.g. CURRENCIES)', example: 'CURRENCIES' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
lookupSource?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Required flag', example: true, default: false })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isRequired?: boolean;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Default value string', example: '600' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
defaultValue?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Placeholder text', example: 'Enter amount' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Help text / instructions', example: 'Allowed compensation amount' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
helpText?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Grid column width (full, half, third, two_thirds)', example: 'half', default: 'full' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
width?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Form section header title', example: 'Financial Details' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
section?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Sorting display order', example: 1, default: 0 })
|
||||||
|
@IsInt()
|
||||||
|
@IsOptional()
|
||||||
|
displayOrder?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Active status flag', example: true, default: true })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Validation rules JSON ({ min, max, regex })' })
|
||||||
|
@IsObject()
|
||||||
|
@IsOptional()
|
||||||
|
validationJson?: Record<string, any>;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ description: 'Visibility condition JSON ({ field, operator, value })' })
|
||||||
|
@IsObject()
|
||||||
|
@IsOptional()
|
||||||
|
visibilityConditionJson?: Record<string, any>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { IsString, IsNotEmpty, IsBoolean, IsOptional, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateMasterDataDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
label: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateOperatorDto {
|
||||||
|
@ApiPropertyOptional({ example: 'EQ', description: 'Unique operator code' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Equals', description: 'Display name of the operator' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '=', description: 'Operator symbol' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
symbol?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 1, description: 'Order used for display sorting' })
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
displayOrder?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: true, description: 'Whether the operator is active' })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsNumber } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateRuleCategoryDto {
|
||||||
|
@ApiPropertyOptional({ example: 'fare-type', description: 'Unique rule category code' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Fare Type', description: 'Display name for the rule category' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Fare-related rule categories', description: 'Optional description' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 1, description: 'Order used for display sorting' })
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
displayOrder?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: true, description: 'Whether the record is active' })
|
||||||
|
@IsBoolean()
|
||||||
|
@IsOptional()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateActionCategoryDto } from './create-action-category.dto';
|
||||||
|
|
||||||
|
export class UpdateActionCategoryDto extends PartialType(CreateActionCategoryDto) {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateActionTypeDto } from './create-action-type.dto';
|
||||||
|
|
||||||
|
export class UpdateActionTypeDto extends PartialType(CreateActionTypeDto) {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateFieldDefinitionDto } from './create-field-definition.dto';
|
||||||
|
|
||||||
|
export class UpdateFieldDefinitionDto extends PartialType(CreateFieldDefinitionDto) {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateMasterDataDto } from './create-master-data.dto';
|
||||||
|
|
||||||
|
export class UpdateMasterDataDto extends PartialType(CreateMasterDataDto) {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateOperatorDto } from './create-operator.dto';
|
||||||
|
|
||||||
|
export class UpdateOperatorDto extends PartialType(CreateOperatorDto) {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateRuleCategoryDto } from './create-rule-category.dto';
|
||||||
|
|
||||||
|
export class UpdateRuleCategoryDto extends PartialType(CreateRuleCategoryDto) {}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
OneToMany,
|
||||||
|
Index,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { ActionType } from './action-type.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_action_categories', schema: 'masters_action_builder' })
|
||||||
|
@Index('UQ_action_category_code', ['code'], { unique: true })
|
||||||
|
export class ActionCategory {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
code!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
displayOrder!: number;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => ActionType, (actionType) => actionType.category)
|
||||||
|
actionTypes?: ActionType[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { ActionSubmission } from './action-submission.entity';
|
||||||
|
import { FieldDefinition } from './field-definition.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_action_submission_values', schema: 'masters_action_builder' })
|
||||||
|
export class ActionSubmissionValue {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
submissionId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ActionSubmission, (submission) => submission.values, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'submissionId' })
|
||||||
|
submission?: ActionSubmission;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid', nullable: true })
|
||||||
|
fieldDefinitionId?: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => FieldDefinition, { onDelete: 'CASCADE', nullable: true })
|
||||||
|
@JoinColumn({ name: 'fieldDefinitionId' })
|
||||||
|
fieldDefinition?: FieldDefinition;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
fieldCode?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'int', default: 0 })
|
||||||
|
valueIndex!: number;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
selectedValueId?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
textValue?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'numeric', nullable: true })
|
||||||
|
numberValue?: number;
|
||||||
|
|
||||||
|
@Column({ type: 'boolean', nullable: true })
|
||||||
|
booleanValue?: boolean;
|
||||||
|
|
||||||
|
@Column({ type: 'date', nullable: true })
|
||||||
|
dateValue?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'time', nullable: true })
|
||||||
|
timeValue?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'timestamptz', nullable: true })
|
||||||
|
timestampValue?: Date;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', length: 10, nullable: true })
|
||||||
|
currencyCode?: string;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
JoinColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { ActionCategory } from './action-category.entity';
|
||||||
|
import { ActionType } from './action-type.entity';
|
||||||
|
import { ActionSubmissionValue } from './action-submission-value.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_action_submissions', schema: 'masters_action_builder' })
|
||||||
|
export class ActionSubmission {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
categoryId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ActionCategory, { onDelete: 'CASCADE', nullable: true })
|
||||||
|
@JoinColumn({ name: 'categoryId' })
|
||||||
|
category?: ActionCategory;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
actionTypeId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ActionType, { onDelete: 'CASCADE', nullable: true })
|
||||||
|
@JoinColumn({ name: 'actionTypeId' })
|
||||||
|
actionType?: ActionType;
|
||||||
|
|
||||||
|
@OneToMany(() => ActionSubmissionValue, (val) => val.submission, { cascade: true })
|
||||||
|
values!: ActionSubmissionValue[];
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinColumn,
|
||||||
|
OneToMany,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { ActionCategory } from './action-category.entity';
|
||||||
|
import { FieldDefinition } from './field-definition.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_action_types', schema: 'masters_action_builder' })
|
||||||
|
export class ActionType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
categoryId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ActionCategory, (category) => category.actionTypes, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'categoryId' })
|
||||||
|
category!: ActionCategory;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
code!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
icon?: string;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
displayOrder!: number;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => FieldDefinition, (field) => field.actionType)
|
||||||
|
fieldDefinitions?: FieldDefinition[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_airline_preferences', schema: 'masters_lookup' })
|
||||||
|
export class AirlinePreference {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_airline_responsibilities', schema: 'masters_lookup' })
|
||||||
|
export class AirlineResponsibility {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_airport_restrictions', schema: 'masters_lookup' })
|
||||||
|
export class AirportRestriction {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_amount_types', schema: 'masters_lookup' })
|
||||||
|
export class AmountType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_ancillary_purchases', schema: 'masters_lookup' })
|
||||||
|
export class AncillaryPurchase {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_applicable_products', schema: 'masters_lookup' })
|
||||||
|
export class ApplicableProduct {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_approval_levels', schema: 'masters_lookup' })
|
||||||
|
export class ApprovalLevel {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_atc_restrictions', schema: 'masters_lookup' })
|
||||||
|
export class AtcRestriction {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_baggage_types', schema: 'masters_lookup' })
|
||||||
|
export class BaggageType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_booking_channels', schema: 'masters_lookup' })
|
||||||
|
export class BookingChannel {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_cabin_classes', schema: 'masters_lookup' })
|
||||||
|
export class CabinClass {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_cabin_preferences', schema: 'masters_lookup' })
|
||||||
|
export class CabinPreference {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_cancellation_reasons', schema: 'masters_lookup' })
|
||||||
|
export class CancellationReason {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_carrier_types', schema: 'masters_lookup' })
|
||||||
|
export class CarrierType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_compensation_bases', schema: 'masters_lookup' })
|
||||||
|
export class CompensationBasis {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_compensation_eligibilities', schema: 'masters_lookup' })
|
||||||
|
export class CompensationEligibility {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_compensation_rules', schema: 'masters_lookup' })
|
||||||
|
export class CompensationRule {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_compensation_types', schema: 'masters_lookup' })
|
||||||
|
export class CompensationType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
import { ConditionGroup } from './condition-group.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_condition_fields', schema: 'masters_rule_engine' })
|
||||||
|
export class ConditionField {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'groupId', type: 'uuid' })
|
||||||
|
groupId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ConditionGroup, (group) => group.fields, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'groupId' })
|
||||||
|
group!: ConditionGroup;
|
||||||
|
|
||||||
|
@Column({ unique: true })
|
||||||
|
code!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'lookupTable', type: 'varchar', nullable: true })
|
||||||
|
lookupTable?: string;
|
||||||
|
|
||||||
|
@Column({ name: 'dataType', type: 'varchar', default: 'STRING' })
|
||||||
|
dataType!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'operatorType', type: 'varchar', default: 'COMPARISON' })
|
||||||
|
operatorType!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'displayOrder', type: 'int', default: 0 })
|
||||||
|
displayOrder!: number;
|
||||||
|
|
||||||
|
@Column({ name: 'isActive', default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'createdAt' })
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn({ name: 'updatedAt' })
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
|
||||||
|
import { ConditionField } from './condition-field.entity';
|
||||||
|
import { RuleCategoryGroup } from './rule-category-group.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_condition_groups', schema: 'masters_rule_engine' })
|
||||||
|
export class ConditionGroup {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ unique: true })
|
||||||
|
code!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Column({ name: 'displayOrder', type: 'int', default: 0 })
|
||||||
|
displayOrder!: number;
|
||||||
|
|
||||||
|
@Column({ name: 'isActive', default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'createdAt' })
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn({ name: 'updatedAt' })
|
||||||
|
updatedAt!: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => ConditionField, (field) => field.group)
|
||||||
|
fields!: ConditionField[];
|
||||||
|
|
||||||
|
@OneToMany(() => RuleCategoryGroup, (rcg) => rcg.conditionGroup)
|
||||||
|
categoryMappings!: RuleCategoryGroup[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_currencies', schema: 'masters_lookup' })
|
||||||
|
export class Currency {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
symbol?: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_customer_values', schema: 'masters_lookup' })
|
||||||
|
export class CustomerValue {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_delay_durations', schema: 'masters_lookup' })
|
||||||
|
export class DelayDuration {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_delay_reasons', schema: 'masters_lookup' })
|
||||||
|
export class DelayReason {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_destination_types', schema: 'masters_lookup' })
|
||||||
|
export class DestinationType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_diversion_reasons', schema: 'masters_lookup' })
|
||||||
|
export class DiversionReason {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_eligible_fare_types', schema: 'masters_lookup' })
|
||||||
|
export class EligibleFareType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_extraordinary_circumstances', schema: 'masters_lookup' })
|
||||||
|
export class ExtraordinaryCircumstance {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_fare_flexibilities', schema: 'masters_lookup' })
|
||||||
|
export class FareFlexibility {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinColumn,
|
||||||
|
Index,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { ActionType } from './action-type.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_field_definitions', schema: 'masters_action_builder' })
|
||||||
|
@Index('UQ_field_definition_action_type_code', ['actionTypeId', 'fieldCode'], { unique: true })
|
||||||
|
export class FieldDefinition {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid' })
|
||||||
|
actionTypeId!: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ActionType, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'actionTypeId' })
|
||||||
|
actionType?: ActionType;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
fieldCode!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
fieldName!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
fieldType!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
lookupSource?: string;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
isRequired!: boolean;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
defaultValue?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
helpText?: string;
|
||||||
|
|
||||||
|
@Column({ default: 'full' })
|
||||||
|
width!: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', nullable: true })
|
||||||
|
section?: string;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
displayOrder!: number;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
|
validationJson?: Record<string, any>;
|
||||||
|
|
||||||
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
|
visibilityConditionJson?: Record<string, any>;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_flight_disruption_types', schema: 'masters_lookup' })
|
||||||
|
export class FlightDisruptionType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_flight_types', schema: 'masters_lookup' })
|
||||||
|
export class FlightType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_goodwill_reasons', schema: 'masters_lookup' })
|
||||||
|
export class GoodwillReason {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_hotel_categories', schema: 'masters_lookup' })
|
||||||
|
export class HotelCategory {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_hotel_chains', schema: 'masters_lookup' })
|
||||||
|
export class HotelChain {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_hotel_tiers', schema: 'masters_lookup' })
|
||||||
|
export class HotelTier {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_journey_types', schema: 'masters_lookup' })
|
||||||
|
export class JourneyType {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_jurisdictions', schema: 'masters_lookup' })
|
||||||
|
export class Jurisdiction {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_loyalty_programs', schema: 'masters_lookup' })
|
||||||
|
export class LoyaltyProgram {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'tbl_meal_categories', schema: 'masters_lookup' })
|
||||||
|
export class MealCategory {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
label!: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
value!: string;
|
||||||
|
|
||||||
|
@Column({ default: true })
|
||||||
|
isActive!: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt!: Date;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user