64 Commits
Author SHA1 Message Date
Syed Waseem khadri Rafai dbc6ffe77a Merge pull request 'development' (#32) from development into test
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/32
2026-08-25 07:22:30 +00:00
Syed Waseem khadri Rafai bf3f987dce Merge pull request 'feat: implement policy applicability and rule evaluation services for policy engine engine' (#31) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/31
2026-08-25 07:22:06 +00:00
Syed Waseem cf458536fb feat: implement policy applicability and rule evaluation services for policy engine engine 2026-08-25 12:50:16 +05:30
Syed Waseem khadri Rafai 287bbb2acd Merge pull request 'development' (#30) from development into test
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/30
2026-08-19 11:04:39 +00:00
Syed Waseem khadri Rafai 2dc4faa410 Merge pull request 'feat: add recovery incident module entities and DTOs and implement policy engine controller endpoints' (#29) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/29
2026-08-19 11:04:21 +00:00
Syed Waseem 5d83099957 feat: add recovery incident module entities and DTOs and implement policy engine controller endpoints 2026-08-19 16:32:39 +05:30
Syed Waseem khadri Rafai 61d5edb7a2 Merge pull request 'feat: implement PolicyApplicabilityService to evaluate policy eligibility based on jurisdiction and cohort matches' (#28) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/28
2026-08-19 09:37:40 +00:00
azeeee05 b8510d9902 feat: implement PolicyApplicabilityService to evaluate policy eligibility based on jurisdiction and cohort matches 2026-08-19 12:31:23 +05:30
Syed Waseem khadri Rafai aaa08ee57f Merge pull request 'development' (#27) from development into test
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/27
2026-08-18 04:42:06 +00:00
Syed Waseem khadri Rafai 6c1a80587e Merge pull request 'waseem' (#26) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/26
2026-08-18 03:58:41 +00:00
Syed Waseem 5780b5cd47 feat: implement policy engine and recovery incident modules with evaluation logic and database schema 2026-08-17 16:38:18 +05:30
Syed Waseem 1d96290618 Merge branch 'development' of https://gitea.maskantech.in/gitea_admin/aeroresolve_backend into waseem 2026-08-17 13:03:40 +05:30
Syed Waseem khadri Rafai b83ec24268 Merge pull request 'feat: implement action builder field configurations and add master data service service layer' (#25) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/25
2026-08-17 06:52:04 +00:00
azeeee05 0a06a3856f feat: implement action builder field configurations and add master data service service layer 2026-08-17 12:12:40 +05:30
Syed Waseem 46770d4b2b feat: implement dashboard module with metrics, exposure, and incident breakdown services 2026-08-13 11:09:01 +05:30
Syed Waseem khadri Rafai e7a9ee911e Merge pull request 'azeem' (#24) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/24
2026-08-12 10:21:35 +00:00
azeeee05 4ee9e36e2b feat: implement MasterDataService with comprehensive entity repositories for application reference data 2026-08-12 15:14:21 +05:30
azeeee05 5779501812 feat: implement master data module with initial entities, action builder configurations, and SQL seed script 2026-08-12 12:46:22 +05:30
Syed Waseem khadri Rafai fd54fc6a0e Merge pull request 'azeem' (#23) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/23
2026-08-11 09:42:22 +00:00
azeeee05 8d11cf85ea feat: implement MasterDataService to manage comprehensive application entities and metadata repositories 2026-08-11 15:08:17 +05:30
azeeee05 9d386580c8 feat: initialize master data entities and seed lookup tables for the rule engine 2026-08-11 14:59:01 +05:30
azeeee05 67756b88bd masters data done 2026-08-11 14:37:42 +05:30
Syed Waseem khadri Rafai 5e4e37c948 Merge pull request 'waseem' (#22) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/22
2026-08-11 07:31:05 +00:00
Syed Waseem dfce163ca0 feat: implement master-data module with core entity definitions, schema migration, and CRUD endpoints 2026-08-11 12:59:01 +05:30
azeeee05 e9f5fd2e7b feat: add RoomType and TaxType entities and update master data module and service seeders 2026-08-11 12:24:53 +05:30
azeeee05 1f8c29d850 feat: initialize master data module with seed script and service structure 2026-08-10 19:23:26 +05:30
azeeee05 689be81442 feat: initialize master data service, entities, and SQL seed script for compensation basis and related parameters 2026-08-10 19:21:45 +05:30
azeeee05 ad90a5b082 feat: extend master-data module with new preference and category entities and initialization script 2026-08-10 19:13:22 +05:30
azeeee05 7f529d8ae4 feat: implement VehicleCategory entity and master data module support 2026-08-10 17:46:23 +05:30
azeeee05 5f95a5c341 feat: initialize master data module with new entity definitions, cohort module, and SQL seeding script 2026-08-10 17:17:06 +05:30
Syed Waseem 06a1ee518e feat: implement recovery incident service and controller with metric aggregation and CRUD operations 2026-08-10 15:18:20 +05:30
azeeee05 e920c9e3b5 Merge branch 'development' of https://gitea.maskantech.in/gitea_admin/aeroresolve_backend into azeem 2026-08-07 16:41:18 +05:30
azeeee05 dbfce10983 feat: initialize backend database schema and implement audit logging system with core service modules 2026-08-07 16:27:15 +05:30
Syed Waseem khadri Rafai a7733ad28f Merge pull request 'feat: add recovery incident module DTO and entity definition' (#21) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/21
2026-08-07 10:57:03 +00:00
Syed Waseem 98df6f18b4 feat: add recovery incident module DTO and entity definition 2026-08-07 16:25:38 +05:30
Syed Waseem khadri Rafai 345d04407a Merge pull request 'feat: implement RecoveryIncident entity and CreateRecoveryIncident DTO' (#20) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/20
2026-08-06 06:44:35 +00:00
azeeee05 e3edd7a6c4 feat: implement RecoveryIncident entity and CreateRecoveryIncident DTO 2026-08-06 11:47:35 +05:30
Syed Waseem khadri Rafai ee7796e6d3 Merge pull request 'feat: implement policy engine entity layer and initial database schema definition' (#19) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/19
2026-08-04 10:28:10 +00:00
Syed Waseem 0d8a6228f4 feat: implement policy engine entity layer and initial database schema definition 2026-08-04 15:45:42 +05:30
Syed Waseem khadri Rafai 03990c71fe Merge pull request 'feat: configure database module with schema initialization and implement recovery incident entity and DTO' (#18) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/18
2026-08-04 10:10:41 +00:00
azeeee05 7413167f79 feat: configure database module with schema initialization and implement recovery incident entity and DTO 2026-08-04 15:39:38 +05:30
Syed Waseem khadri Rafai 2c0cad7093 Merge pull request 'recovery incidents' (#17) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/17
2026-08-04 09:16:34 +00:00
azeeee05 86f435500a recovery incidents 2026-08-03 14:26:19 +05:30
Syed Waseem khadri Rafai a8c8b11ba5 Merge pull request 'feat: implement master data entities and initial database schema for the policy engine module' (#16) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/16
2026-08-03 06:20:06 +00:00
Syed Waseem 9f3b3ad4fd feat: implement master data entities and initial database schema for the policy engine module 2026-08-03 11:45:26 +05:30
Syed Waseem khadri Rafai 7afd58c178 Merge pull request 'feat: implement master data service and seed scripts for reference table management' (#15) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/15
2026-07-29 10:39:33 +00:00
Syed Waseem 1fe403cb11 feat: implement master data service and seed scripts for reference table management 2026-07-29 16:07:11 +05:30
Syed Waseem khadri Rafai e209541475 Merge pull request 'waseem' (#14) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/14
2026-07-29 09:48:50 +00:00
Syed Waseem 046d36d069 feat: implement comprehensive master data module with CRUD services, controllers, and entities 2026-07-29 15:13:41 +05:30
maskantech 393963a982 Merge pull request 'Update README.md' (#13) from deploy into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/13
2026-07-21 17:49:16 +00:00
maskantech 5cd42c914f Update README.md 2026-07-21 17:48:55 +00:00
maskantech c90c96b8e5 Merge pull request 'Update README.md' (#12) from deploy into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/12
2026-07-21 17:45:10 +00:00
maskantech 9cf49bc05e Update README.md 2026-07-21 17:44:52 +00:00
maskantech 894660b865 Merge pull request 'Update README.md' (#11) from deploy into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/11
2026-07-21 17:34:22 +00:00
maskantech 1d4b160660 Update README.md 2026-07-21 17:34:07 +00:00
maskantech a5770d1e0f Merge pull request 'Update README.md' (#10) from deploy into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/10
2026-07-21 17:26:31 +00:00
maskantech 2cdd921012 Update README.md 2026-07-21 17:25:55 +00:00
maskantech bef7aa98c1 Merge pull request 'Update README.md' (#9) from deploy into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/9
2026-07-21 11:25:30 +00:00
maskantech dfd2ff8127 Update README.md 2026-07-21 11:25:05 +00:00
Syed Waseem e8e6da31be feat: update entity properties to use definite assignment assertion and add unique indexes for tenant-specific codes 2026-07-21 13:17:08 +05:30
Syed Waseem khadri Rafai de7527e1bd Merge pull request 'waseem' (#8) from waseem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_backend/pulls/8
2026-07-21 05:54:34 +00:00
Syed Waseem f3acfd2181 feat(master-data): add jurisdiction and rule category entities with CRUD operations
- Introduced Jurisdiction and RuleCategory entities along with their respective values.
- Implemented service methods for managing rule categories and values.
- Updated MasterDataService to include seeding logic for jurisdictions and rule categories.
- Added DTOs for creating and updating rule categories and values.

feat(policy-engine): enhance policy management with new entities and operations

- Created Policy, PolicyRule, PolicyAction, PolicyTargetAudience, and RuleCondition entities.
- Implemented create, update, and delete operations for policies and their associated rules and actions.
- Added enums for PolicyStatus and AudienceType to manage policy states and target audiences.
- Developed DTOs for creating and updating policies with nested structures for rules and audiences.
2026-07-21 11:22:54 +05:30
Syed Waseem 4fd1058dfe Merge branch 'development' of https://gitea.maskantech.in/gitea_admin/aeroresolve_backend into waseem 2026-07-18 11:13:00 +05:30
waseem khadri fd196f559b feat: initialize policy-engine module and integrate into AppModule 2026-07-15 09:04:42 +05:30
140 changed files with 10340 additions and 302 deletions
+19 -18
View File
@@ -1,15 +1,16 @@
# AeroResolve Backend
test1
NestJS REST API for AeroResolve.
## Current Modules
| Module | Status | Description |
|--------|--------|-------------|
| `health` | Implemented | Health check |
| `database` | Implemented | PostgreSQL / TypeORM setup |
| Module | Status | Description |
| ------------- | ----------- | ---------------------------------------- |
| `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 |
| `cohort` | Implemented | Cohort CRUD, pagination, status update |
## Prerequisites
@@ -80,20 +81,20 @@ 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` |
| 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` |
| `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
+136
View File
@@ -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
}
]
}
]
+94
View File
@@ -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"
}
]
}
]
+311
View File
@@ -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
}
]
}
]
+133
View File
@@ -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
}
]
}
]
+155
View File
@@ -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
}
]
}
]
+480 -42
View File
@@ -3,23 +3,44 @@
-- PostgreSQL 14+
-- Generated from TypeORM entities (aeroresolve_backend)
-- =============================================================================
--
-- Usage:
-- psql -h <host> -U <user> -d <database> -f database/schema.sql
--
-- Notes:
-- - Column names use camelCase to match TypeORM entity field names.
-- - In local/dev, TypeORM can also sync via DB_SYNCHRONIZE=true.
-- - Run scripts/seed-master-data.ts after schema creation for demo data.
-- =============================================================================
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- ─── Schemas ────────────────────────────────────────────────────────────────
CREATE SCHEMA IF NOT EXISTS tenant;
CREATE SCHEMA IF NOT EXISTS masters;
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 ─────────────────────────────────────────────────────────────
@@ -56,95 +77,437 @@ CREATE TABLE IF NOT EXISTS tenant.tbl_tenants (
CONSTRAINT uq_tbl_tenants_slug UNIQUE (slug)
);
-- ─── Master Data ────────────────────────────────────────────────────────────
-- ─── 1. Masters Lookup Schema (Domain Master Tables) ─────────────────────────
CREATE TABLE IF NOT EXISTS masters.tbl_membership_tiers (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_membership_tiers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_membership_tiers_tenant ON masters.tbl_membership_tiers("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_customer_values (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_customer_values (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_customer_values_tenant ON masters.tbl_customer_values("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_regions (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_regions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_regions_tenant ON masters.tbl_regions("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_trip_purposes (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_trip_purposes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_trip_purposes_tenant ON masters.tbl_trip_purposes("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_cabin_classes (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_cabin_classes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_cabin_classes_tenant ON masters.tbl_cabin_classes("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_passenger_types (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_passenger_types (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_passenger_types_tenant ON masters.tbl_passenger_types("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_ancillary_purchases (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_ancillary_purchases (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_ancillary_purchases_tenant ON masters.tbl_ancillary_purchases("tenantId");
CREATE TABLE IF NOT EXISTS masters.tbl_revenue_segments (
CREATE TABLE IF NOT EXISTS masters_lookup.tbl_revenue_segments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
"tenantId" UUID NOT NULL REFERENCES tenant.tbl_tenants(id) ON DELETE CASCADE,
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 INDEX IF NOT EXISTS idx_tbl_revenue_segments_tenant ON masters.tbl_revenue_segments("tenantId");
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 ────────────────────────────────────────────────────────────────
@@ -168,42 +531,117 @@ CREATE INDEX IF NOT EXISTS idx_tbl_cohorts_tenant ON cohort.tbl_cohorts("tenantI
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.tbl_cabin_classes(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.tbl_passenger_types(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.tbl_ancillary_purchases(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.tbl_membership_tiers(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.tbl_revenue_segments(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.tbl_regions(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.tbl_trip_purposes(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);
+939
View File
@@ -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);
+7 -7
View File
@@ -2394,14 +2394,14 @@
}
},
"node_modules/@nestjs/platform-express": {
"version": "11.1.27",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.27.tgz",
"integrity": "sha512-0ZFhz6H6EdGh4xQVbUNwjoAwBuz73P7FvUAl67h9CTdMqQlJDaQYJApBv8pKfVZ1fGjMCbl0m9DcC6pXaZPWSQ==",
"version": "11.1.28",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.28.tgz",
"integrity": "sha512-hU+9Sz4m+onHrR5AmelI59QKmY/Re546bPnygnpqqeQdHDiJpBgjWbL4t6Jr73CBpS60cpyng7WzjgphNB9iwA==",
"license": "MIT",
"dependencies": {
"cors": "2.8.6",
"express": "5.2.1",
"multer": "2.1.1",
"multer": "2.2.0",
"path-to-regexp": "8.4.2",
"tslib": "2.8.1"
},
@@ -7873,9 +7873,9 @@
"license": "MIT"
},
"node_modules/multer": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz",
"integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/multer/-/multer-2.2.0.tgz",
"integrity": "sha512-6rdyFg2kLrMh9Jee7/BMPuV9lEAd7lLW2YUpF9/YxR7njyoUwwQ0ZPh3TaIY50Sw6vlyD2HW3wGOkTS4P79xrQ==",
"license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
+1 -5
View File
@@ -15,11 +15,7 @@ async function bootstrap() {
const tenants = await tenantService.seedDemoTenants();
logger.log(`Seeded ${tenants.length} demo tenant(s)`);
for (const tenant of tenants) {
await masterDataService.seedData(tenant.id);
logger.log(`Master data ready for tenant: ${tenant.slug}`);
}
logger.log('Master data ready (common across all tenants).');
logger.log('Seeding complete. Exiting...');
+16
View File
@@ -1,4 +1,5 @@
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { ConfigModule } from '@nestjs/config';
import { DatabaseModule } from './database/database.module';
import { HealthModule } from './modules/health/health.module';
@@ -6,6 +7,11 @@ 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'];
@@ -21,6 +27,16 @@ const envFilePath = env ? [`.env.${env}`, '.env.local', '.env'] : ['.env.local',
TenantModule,
MasterDataModule,
CohortModule,
PolicyEngineModule,
RecoveryIncidentModule,
AuditLogModule,
DashboardModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: AuditInterceptor,
},
],
})
export class AppModule implements NestModule {
+2 -2
View File
@@ -4,9 +4,9 @@ import { Tenant } from '../../modules/tenant/tenant.entity';
export abstract class TenantOwnedEntity {
@Column({ type: 'uuid' })
@Index()
tenantId: string;
tenantId!: string;
@ManyToOne(() => Tenant, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'tenantId' })
tenant: Tenant;
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}`);
}
},
}),
);
}
}
+2 -2
View File
@@ -17,9 +17,9 @@ export class TenantMiddleware implements NestMiddleware {
return next();
}
const tenantHeader = req.headers['x-tenant-id'];
let tenantHeader = req.headers['x-tenant-id'];
if (!tenantHeader || Array.isArray(tenantHeader)) {
throw new BadRequestException('Missing X-Tenant-Id header');
tenantHeader = 'demo-airline';
}
try {
+11 -6
View File
@@ -28,20 +28,25 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
// Initialize without syncing first
const dataSource = new DataSource({ ...options, synchronize: false });
await dataSource.initialize();
// Create schemas if they don't exist
// 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";`);
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 {}
export class DatabaseModule { }
@@ -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;
}
}
+13
View File
@@ -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;
}
+25 -25
View File
@@ -11,101 +11,101 @@ import { TripPurpose } from '../master-data/entities/trip-purpose.entity';
@Entity({ name: 'tbl_cohorts', schema: 'cohort' })
export class Cohort extends TenantOwnedEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column({ nullable: true })
scopeType: string;
scopeType!: string;
@Column()
name: string;
name!: string;
@Column({ nullable: true })
description: string;
description!: string;
@Column({ default: 'Draft' })
status: string; // Draft, Active, Inactive
status!: string; // Draft, Active, Inactive
// Passenger Attributes
@ManyToMany(() => CabinClass)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_cabin_classes',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'cabinClassId', referencedColumnName: 'id' }
})
cabinClasses: CabinClass[];
cabinClasses!: CabinClass[];
@ManyToMany(() => PassengerType)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_passenger_types',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'passengerTypeId', referencedColumnName: 'id' }
})
passengerTypes: PassengerType[];
passengerTypes!: PassengerType[];
@ManyToMany(() => AncillaryPurchase)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_ancillary_purchases',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'ancillaryPurchaseId', referencedColumnName: 'id' }
})
ancillaryPurchases: AncillaryPurchase[];
ancillaryPurchases!: AncillaryPurchase[];
// Customer Value
@ManyToMany(() => MembershipTier)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_loyalty_tiers',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'membershipTierId', referencedColumnName: 'id' }
})
loyaltyTiers: MembershipTier[];
loyaltyTiers!: MembershipTier[];
@ManyToMany(() => RevenueSegment)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_revenue_segments',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'revenueSegmentId', referencedColumnName: 'id' }
})
revenueSegments: RevenueSegment[];
revenueSegments!: RevenueSegment[];
@Column({
type: 'enum',
enum: ['Any', 'Yes(VIP/Strategic)', 'No'],
default: 'Any'
})
highValuePassenger: string;
highValuePassenger!: string;
@Column({
type: 'enum',
enum: ['Domestic Only', 'International Only', 'Both (All)'],
nullable: true
})
flightType: string;
flightType!: string;
@ManyToMany(() => Region)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_regions',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'regionId', referencedColumnName: 'id' }
})
regions: Region[];
regions!: Region[];
@ManyToMany(() => TripPurpose)
@JoinTable({
@JoinTable({
name: 'tbl_cohort_trip_purposes',
joinColumn: { name: 'cohortId', referencedColumnName: 'id' },
inverseJoinColumn: { name: 'tripPurposeId', referencedColumnName: 'id' }
})
tripPurposes: TripPurpose[];
tripPurposes!: TripPurpose[];
@Column('simple-array', { nullable: true })
originAirport: string[];
originAirport!: string[];
@Column('simple-array', { nullable: true })
destinationAirport: string[];
destinationAirport!: string[];
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
updatedAt!: Date;
}
+3 -1
View File
@@ -1,11 +1,13 @@
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])],
imports: [TypeOrmModule.forFeature([Cohort]), AuditLogModule],
controllers: [CohortController],
providers: [CohortService],
exports: [CohortService],
+41 -2
View File
@@ -5,12 +5,14 @@ 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) {
@@ -96,19 +98,56 @@ export class CohortService {
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);
return this.cohortRepository.save(cohort);
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;
return this.cohortRepository.save(cohort);
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(),
});
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { IsString, IsNotEmpty, IsOptional, IsArray } from 'class-validator';
export class CreateCohortDto {
@IsString()
@IsNotEmpty()
name: string;
name!: string;
@IsString()
@IsOptional()
@@ -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();
}
}
+18
View File
@@ -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 {}
+244
View File
@@ -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',
}));
}
}
@@ -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,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 { 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;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_ancillary_purchases', schema: 'masters' })
export class AncillaryPurchase extends TenantOwnedEntity {
@Entity({ name: 'tbl_ancillary_purchases', schema: 'masters_lookup' })
export class AncillaryPurchase {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
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;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_cabin_classes', schema: 'masters' })
export class CabinClass extends TenantOwnedEntity {
@Entity({ name: 'tbl_cabin_classes', schema: 'masters_lookup' })
export class CabinClass {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
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;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_customer_values', schema: 'masters' })
export class CustomerValue extends TenantOwnedEntity {
@Entity({ name: 'tbl_customer_values', schema: 'masters_lookup' })
export class CustomerValue {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
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;
}
@@ -0,0 +1,28 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'tbl_meal_types', schema: 'masters_lookup' })
export class MealType {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
label!: string;
@Column()
value!: string;
@Column({ default: true })
isActive!: boolean;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_membership_tiers', schema: 'masters' })
export class MembershipTier extends TenantOwnedEntity {
@Entity({ name: 'tbl_membership_tiers', schema: 'masters_lookup' })
export class MembershipTier {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
updatedAt!: Date;
}
@@ -0,0 +1,28 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'tbl_missed_connection_reasons', schema: 'masters_lookup' })
export class MissedConnectionReason {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
label!: string;
@Column()
value!: string;
@Column({ default: true })
isActive!: boolean;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
@@ -0,0 +1,36 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
Index,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'tbl_operators', schema: 'masters_rule_engine' })
@Index('UQ_operator_code', ['code'], { unique: true })
export class Operator {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
code!: string;
@Column()
name!: string;
@Column({ nullable: true })
symbol?: string;
@Column({ default: true })
isActive!: boolean;
@Column({ default: 0 })
displayOrder!: number;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_passenger_types', schema: 'masters' })
export class PassengerType extends TenantOwnedEntity {
@Entity({ name: 'tbl_passenger_types', schema: 'masters_lookup' })
export class PassengerType {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
updatedAt!: Date;
}
@@ -0,0 +1,28 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'tbl_promotion_codes', schema: 'masters_lookup' })
export class PromotionCode {
@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_refund_bases', schema: 'masters_lookup' })
export class RefundBasis {
@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_refund_components', schema: 'masters_lookup' })
export class RefundComponent {
@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_refund_methods', schema: 'masters_lookup' })
export class RefundMethod {
@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_refund_types', schema: 'masters_lookup' })
export class RefundType {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
label!: string;
@Column()
value!: string;
@Column({ default: true })
isActive!: boolean;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_regions', schema: 'masters' })
export class Region extends TenantOwnedEntity {
@Entity({ name: 'tbl_regions', schema: 'masters_lookup' })
export class Region {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
updatedAt!: Date;
}
@@ -5,25 +5,24 @@ import {
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { TenantOwnedEntity } from '../../../common/entities/tenant-owned.entity';
@Entity({ name: 'tbl_revenue_segments', schema: 'masters' })
export class RevenueSegment extends TenantOwnedEntity {
@Entity({ name: 'tbl_revenue_segments', schema: 'masters_lookup' })
export class RevenueSegment {
@PrimaryGeneratedColumn('uuid')
id: string;
id!: string;
@Column()
label: string;
label!: string;
@Column()
value: string;
value!: string;
@Column({ default: true })
isActive: boolean;
isActive!: boolean;
@CreateDateColumn()
createdAt: Date;
createdAt!: Date;
@UpdateDateColumn()
updatedAt: Date;
updatedAt!: Date;
}
@@ -0,0 +1,28 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'tbl_room_types', schema: 'masters_lookup' })
export class RoomType {
@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_routes', schema: 'masters_lookup' })
export class Route {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
label!: string;
@Column()
value!: string;
@Column({ default: true })
isActive!: boolean;
@CreateDateColumn()
createdAt!: Date;
@UpdateDateColumn()
updatedAt!: Date;
}
@@ -0,0 +1,27 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn, Unique } from 'typeorm';
import { RuleCategory } from './rule-category.entity';
import { ConditionGroup } from './condition-group.entity';
@Entity({ name: 'tbl_rule_category_groups', schema: 'masters_rule_engine' })
@Unique(['ruleCategoryId', 'conditionGroupId'])
export class RuleCategoryGroup {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column({ name: 'ruleCategoryId', type: 'uuid' })
ruleCategoryId!: string;
@ManyToOne(() => RuleCategory, (rc) => rc.groupMappings, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'ruleCategoryId' })
ruleCategory!: RuleCategory;
@Column({ name: 'conditionGroupId', type: 'uuid' })
conditionGroupId!: string;
@ManyToOne(() => ConditionGroup, (cg) => cg.categoryMappings, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'conditionGroupId' })
conditionGroup!: ConditionGroup;
@CreateDateColumn({ name: 'createdAt' })
createdAt!: Date;
}
@@ -0,0 +1,45 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
Index,
UpdateDateColumn,
OneToMany,
} from 'typeorm';
import { RuleCategoryGroup } from './rule-category-group.entity';
@Entity({ name: 'tbl_rules_categories', schema: 'masters_rule_engine' })
@Index('UQ_rule_category_code', ['code'], { unique: true })
export class RuleCategory {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
code!: string;
@Column()
name!: string;
@Column({ type: 'varchar', nullable: true })
tableName?: 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(() => RuleCategoryGroup, (rcg) => rcg.ruleCategory)
groupMappings!: RuleCategoryGroup[];
}

Some files were not shown because too many files have changed in this diff Show More