Compare commits
76 Commits
split-serv
...
split-sche
| Author | SHA1 | Date | |
|---|---|---|---|
| 50f93bbeae | |||
| 3ce9d1d180 | |||
| cb819088a0 | |||
| 8f5f01c287 | |||
| e4a2a04045 | |||
| 50ce8e39c5 | |||
| 19e57f0e7f | |||
| ad5e343b66 | |||
| 8c3ece6ebd | |||
| 092f425bb3 | |||
| b1a3afd3a1 | |||
| 97f431260d | |||
| bf6d9ae00b | |||
| 518ec4eb21 | |||
| 95b061b400 | |||
| 92992797ab | |||
| c96e3b0c1a | |||
| f23b93801c | |||
| f1801a3210 | |||
| 2588ca4317 | |||
| e809ba4480 | |||
| 678be7c905 | |||
| 08b4231e5f | |||
|
|
4a61e2c412 | ||
| a3ab9db5a2 | |||
|
|
7167eae07e | ||
|
|
4f3d7fd737 | ||
|
|
199013b0f5 | ||
| 0b81dbf7b1 | |||
|
|
9722e1988c | ||
| cf2bbbf138 | |||
|
|
2ca785248f | ||
| 0aa2b9b53e | |||
| b5cdb20c4f | |||
| 00e07113e5 | |||
| c8f0f93792 | |||
| 87779664d1 | |||
| 5b31e5f2a9 | |||
| 2a073c44a2 | |||
|
|
220d309087 | ||
| f45c33ba83 | |||
| 22b3593150 | |||
| d186681ee4 | |||
| 8f428fc1cb | |||
| 0b503cf8bb | |||
| 7110d0462c | |||
| 96648fe37e | |||
|
|
2095f8e124 | ||
| 21c8799502 | |||
|
|
ad9e8e1a3f | ||
| b200e2cb94 | |||
| cae66237d2 | |||
| 25be8a5647 | |||
| 7a4aecdd45 | |||
| 5cced2981a | |||
|
|
b9fbab3717 | ||
|
|
90c897ad48 | ||
| 4a069cc67a | |||
|
|
5d046c4bcf | ||
| accfc4b769 | |||
| e149884f72 | |||
| a31ec97640 | |||
| 0c97412057 | |||
|
|
b4ff39c0d7 | ||
| bb5da7647b | |||
| 3f19bb4087 | |||
| be8b9cef7d | |||
|
|
77cef98091 | ||
| 97f9c2b26e | |||
|
|
b93cd6b32c | ||
|
|
51319a69fc | ||
| 5ad46309ef | |||
|
|
781212277a | ||
| 6b0ee461c5 | |||
| cc2fa3eb6b | |||
| fe6bb59cc7 |
@@ -1,40 +0,0 @@
|
|||||||
# Split Serverless services (deploy order)
|
|
||||||
|
|
||||||
This repo is split into multiple Serverless configs so you can deploy smaller CloudFormation stacks instead of one huge stack.
|
|
||||||
|
|
||||||
## Config files
|
|
||||||
|
|
||||||
- `serverless.layers.yml`: Prisma layer stack (deploy once per stage)
|
|
||||||
- `serverless.host.yml`: Host + PQQ functions (owns the shared HTTP API)
|
|
||||||
- `serverless.admin.yml`: Minglar Admin functions (attaches routes to Host HTTP API)
|
|
||||||
- `serverless.user.yml`: User functions (attaches routes to Host HTTP API)
|
|
||||||
- `serverless.prepopulate.yml`: Prepopulate functions (attaches routes to Host HTTP API)
|
|
||||||
|
|
||||||
## Deploy order (per stage)
|
|
||||||
|
|
||||||
1) Deploy the layer:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx serverless deploy --config serverless.layers.yml --stage dev
|
|
||||||
```
|
|
||||||
|
|
||||||
2) Deploy Host (creates the HTTP API + routes for host functions):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx serverless deploy --config serverless.host.yml --stage dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3) Deploy remaining services (they reuse Host's HTTP API id):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx serverless deploy --config serverless.admin.yml --stage dev
|
|
||||||
npx serverless deploy --config serverless.user.yml --stage dev
|
|
||||||
npx serverless deploy --config serverless.prepopulate.yml --stage dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deploy a single function
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx serverless deploy function --config serverless.host.yml --stage dev -f getHosts
|
|
||||||
```
|
|
||||||
|
|
||||||
533
package-lock.json
generated
533
package-lock.json
generated
@@ -13,7 +13,7 @@
|
|||||||
"@aws-crypto/sha256-browser": "^5.2.0",
|
"@aws-crypto/sha256-browser": "^5.2.0",
|
||||||
"@aws-crypto/sha256-js": "^5.2.0",
|
"@aws-crypto/sha256-js": "^5.2.0",
|
||||||
"@aws-sdk/client-s3": "^3.928.0",
|
"@aws-sdk/client-s3": "^3.928.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.310.0",
|
"@aws-sdk/s3-request-presigner": "^3.928.0",
|
||||||
"@aws/lambda-invoke-store": "^0.2.1",
|
"@aws/lambda-invoke-store": "^0.2.1",
|
||||||
"@nestjs/common": "^10.3.0",
|
"@nestjs/common": "^10.3.0",
|
||||||
"@nestjs/config": "^3.1.1",
|
"@nestjs/config": "^3.1.1",
|
||||||
@@ -31,18 +31,27 @@
|
|||||||
"@types/http-status": "^1.1.2",
|
"@types/http-status": "^1.1.2",
|
||||||
"ajv": "8.12.0",
|
"ajv": "8.12.0",
|
||||||
"aws-lambda": "^1.0.7",
|
"aws-lambda": "^1.0.7",
|
||||||
|
"aws-sdk": "^2.1692.0",
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"dayjs": "^1.11.19",
|
||||||
|
"docx": "^9.6.0",
|
||||||
|
"docxtemplater": "^3.68.3",
|
||||||
"fast-xml-parser": "^5.3.1",
|
"fast-xml-parser": "^5.3.1",
|
||||||
|
"fs": "^0.0.1-security",
|
||||||
"helmet": "^7.1.0",
|
"helmet": "^7.1.0",
|
||||||
"http-status": "^2.1.0",
|
"http-status": "^2.1.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
|
"number-to-words": "^1.2.4",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
"path": "^0.12.7",
|
||||||
|
"pdf-lib": "^1.17.1",
|
||||||
|
"pizzip": "^3.2.0",
|
||||||
"prisma": "^7.0.1",
|
"prisma": "^7.0.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
@@ -73,6 +82,7 @@
|
|||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"serverless-esbuild": "^1.55.1",
|
"serverless-esbuild": "^1.55.1",
|
||||||
"serverless-offline": "^14.4.0",
|
"serverless-offline": "^14.4.0",
|
||||||
|
"serverless-plugin-split-stacks": "^1.14.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "^6.3.4",
|
"supertest": "^6.3.4",
|
||||||
"ts-jest": "^29.1.2",
|
"ts-jest": "^29.1.2",
|
||||||
@@ -4650,6 +4660,24 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@pdf-lib/standard-fonts": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pako": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@pdf-lib/upng": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pako": "^1.0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pkgjs/parseargs": {
|
"node_modules/@pkgjs/parseargs": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||||
@@ -5751,6 +5779,13 @@
|
|||||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@tootallnate/quickjs-emscripten": {
|
||||||
|
"version": "0.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
|
||||||
|
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@tsconfig/node10": {
|
"node_modules/@tsconfig/node10": {
|
||||||
"version": "1.0.12",
|
"version": "1.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
|
||||||
@@ -6546,6 +6581,15 @@
|
|||||||
"@xtuc/long": "4.2.2"
|
"@xtuc/long": "4.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@xmldom/xmldom": {
|
||||||
|
"version": "0.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.8.tgz",
|
||||||
|
"integrity": "sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@xtuc/ieee754": {
|
"node_modules/@xtuc/ieee754": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||||
@@ -6624,6 +6668,16 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "7.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||||
|
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/aggregate-error": {
|
"node_modules/aggregate-error": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||||
@@ -6964,6 +7018,19 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/ast-types": {
|
||||||
|
"version": "0.13.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
|
||||||
|
"integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/async": {
|
"node_modules/async": {
|
||||||
"version": "3.2.6",
|
"version": "3.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||||
@@ -6992,6 +7059,13 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/aws-info": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-info/-/aws-info-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-dYE3J2GQOMXjirx54IonDisZ6Ok4vBSYjNklNAGGDj2FzGHkWpGOlGAn5/BC8TRh8ttmYRy+Fsmxc8EJMnzSCg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/aws-lambda": {
|
"node_modules/aws-lambda": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/aws-lambda/-/aws-lambda-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/aws-lambda/-/aws-lambda-1.0.7.tgz",
|
||||||
@@ -7257,6 +7331,16 @@
|
|||||||
"baseline-browser-mapping": "dist/cli.js"
|
"baseline-browser-mapping": "dist/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/basic-ftp": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bcrypt": {
|
"node_modules/bcrypt": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
||||||
@@ -8386,7 +8470,6 @@
|
|||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/cors": {
|
"node_modules/cors": {
|
||||||
@@ -8539,6 +8622,12 @@
|
|||||||
"url": "https://github.com/sponsors/kossnocorp"
|
"url": "https://github.com/sponsors/kossnocorp"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dayjs": {
|
||||||
|
"version": "1.11.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||||
|
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
@@ -8633,6 +8722,21 @@
|
|||||||
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/degenerator": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ast-types": "^0.13.4",
|
||||||
|
"escodegen": "^2.1.0",
|
||||||
|
"esprima": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/delayed-stream": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
@@ -8763,6 +8867,50 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/docx": {
|
||||||
|
"version": "9.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/docx/-/docx-9.6.0.tgz",
|
||||||
|
"integrity": "sha512-y6EaJJMDvt4P7wgGQB9KsZf4wsRkQMJfkc9LlNufRshggI5BT35hGNkXBCAeEoI3MLMwApKguxzjdqqVcBCqNA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^25.2.3",
|
||||||
|
"hash.js": "^1.1.7",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
|
"nanoid": "^5.1.3",
|
||||||
|
"xml": "^1.0.1",
|
||||||
|
"xml-js": "^1.6.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/docx/node_modules/@types/node": {
|
||||||
|
"version": "25.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz",
|
||||||
|
"integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/docx/node_modules/undici-types": {
|
||||||
|
"version": "7.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/docxtemplater": {
|
||||||
|
"version": "3.68.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/docxtemplater/-/docxtemplater-3.68.3.tgz",
|
||||||
|
"integrity": "sha512-hTZfGcHgN60A09w68Qj0EQRCnF5kf2/ohFlZlUVqAOozCFwx9QMm8naCTvmTsXafuO3nG9qpS4pQWSjFdaCWfQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@xmldom/xmldom": "^0.9.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "16.4.5",
|
"version": "16.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||||
@@ -9031,6 +9179,39 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/escodegen": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"esprima": "^4.0.1",
|
||||||
|
"estraverse": "^5.2.0",
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"escodegen": "bin/escodegen.js",
|
||||||
|
"esgenerate": "bin/esgenerate.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"source-map": "~0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/escodegen/node_modules/source-map": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.57.1",
|
"version": "8.57.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
|
||||||
@@ -10022,6 +10203,12 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fs": {
|
||||||
|
"version": "0.0.1-security",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||||
|
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/fs-constants": {
|
"node_modules/fs-constants": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
@@ -10199,6 +10386,31 @@
|
|||||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-uri": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"basic-ftp": "^5.0.2",
|
||||||
|
"data-uri-to-buffer": "^6.0.2",
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-uri/node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/giget": {
|
"node_modules/giget": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
||||||
@@ -10437,6 +10649,16 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hash.js": {
|
||||||
|
"version": "1.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
|
||||||
|
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"minimalistic-assert": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
@@ -10499,6 +10721,20 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/http-proxy-agent": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.0",
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-status": {
|
"node_modules/http-status": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-status/-/http-status-2.1.0.tgz",
|
||||||
@@ -10514,6 +10750,20 @@
|
|||||||
"integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==",
|
"integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/human-signals": {
|
"node_modules/human-signals": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
@@ -10556,7 +10806,6 @@
|
|||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
@@ -10661,6 +10910,16 @@
|
|||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ip-address": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ipaddr.js": {
|
"node_modules/ipaddr.js": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
@@ -11986,7 +12245,6 @@
|
|||||||
"version": "3.10.1",
|
"version": "3.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||||
"dev": true,
|
|
||||||
"license": "(MIT OR GPL-3.0-or-later)",
|
"license": "(MIT OR GPL-3.0-or-later)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lie": "~3.3.0",
|
"lie": "~3.3.0",
|
||||||
@@ -11999,7 +12257,6 @@
|
|||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
@@ -12015,14 +12272,12 @@
|
|||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/jszip/node_modules/string_decoder": {
|
"node_modules/jszip/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
@@ -12149,7 +12404,6 @@
|
|||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"immediate": "~3.0.5"
|
"immediate": "~3.0.5"
|
||||||
@@ -12548,6 +12802,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimalistic-assert": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.3",
|
"version": "9.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||||
@@ -12698,6 +12958,24 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nanoid": {
|
||||||
|
"version": "5.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz",
|
||||||
|
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"nanoid": "bin/nanoid.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18 || >=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@@ -12722,6 +13000,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/netmask": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nock": {
|
"node_modules/nock": {
|
||||||
"version": "13.5.6",
|
"version": "13.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz",
|
||||||
@@ -12873,6 +13161,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/number-to-words": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/number-to-words/-/number-to-words-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-/fYevVkXRcyBiZDg6yzZbm0RuaD6i0qRfn8yr+6D0KgBMOndFPxuW10qCHpzs50nN8qKuv78k8MuotZhcVX6Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/nypm": {
|
"node_modules/nypm": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
|
||||||
@@ -13118,6 +13412,40 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pac-proxy-agent": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tootallnate/quickjs-emscripten": "^0.23.0",
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"get-uri": "^6.0.1",
|
||||||
|
"http-proxy-agent": "^7.0.0",
|
||||||
|
"https-proxy-agent": "^7.0.6",
|
||||||
|
"pac-resolver": "^7.0.1",
|
||||||
|
"socks-proxy-agent": "^8.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pac-resolver": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"degenerator": "^5.0.0",
|
||||||
|
"netmask": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/package-json-from-dist": {
|
"node_modules/package-json-from-dist": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||||
@@ -13128,7 +13456,6 @@
|
|||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||||
"dev": true,
|
|
||||||
"license": "(MIT AND Zlib)"
|
"license": "(MIT AND Zlib)"
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
@@ -13219,6 +13546,16 @@
|
|||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/path": {
|
||||||
|
"version": "0.12.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
|
||||||
|
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"process": "^0.11.1",
|
||||||
|
"util": "^0.10.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
@@ -13293,6 +13630,21 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/path/node_modules/inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/path/node_modules/util": {
|
||||||
|
"version": "0.10.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
|
||||||
|
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pathe": {
|
"node_modules/pathe": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
@@ -13304,6 +13656,24 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
|
||||||
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
|
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/pdf-lib": {
|
||||||
|
"version": "1.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz",
|
||||||
|
"integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@pdf-lib/standard-fonts": "^1.0.0",
|
||||||
|
"@pdf-lib/upng": "^1.0.1",
|
||||||
|
"pako": "^1.0.11",
|
||||||
|
"tslib": "^1.11.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pdf-lib/node_modules/tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
"node_modules/perfect-debounce": {
|
"node_modules/perfect-debounce": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
||||||
@@ -13438,6 +13808,21 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pizzip": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pizzip/-/pizzip-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-X4NPNICxCfIK8VYhF6wbksn81vTiziyLbvKuORVAmolvnUzl1A1xmz9DAWKxPRq9lZg84pJOOAMq3OE61bD8IQ==",
|
||||||
|
"license": "(MIT OR GPL-3.0)",
|
||||||
|
"dependencies": {
|
||||||
|
"pako": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pizzip/node_modules/pako": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||||
|
"license": "(MIT AND Zlib)"
|
||||||
|
},
|
||||||
"node_modules/pkg-dir": {
|
"node_modules/pkg-dir": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
@@ -13689,11 +14074,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process": {
|
||||||
|
"version": "0.11.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
|
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/prompts": {
|
"node_modules/prompts": {
|
||||||
@@ -13756,6 +14149,36 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proxy-agent": {
|
||||||
|
"version": "6.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
|
||||||
|
"integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"http-proxy-agent": "^7.0.1",
|
||||||
|
"https-proxy-agent": "^7.0.6",
|
||||||
|
"lru-cache": "^7.14.1",
|
||||||
|
"pac-proxy-agent": "^7.1.0",
|
||||||
|
"proxy-from-env": "^1.1.0",
|
||||||
|
"socks-proxy-agent": "^8.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/proxy-agent/node_modules/lru-cache": {
|
||||||
|
"version": "7.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
@@ -14756,6 +15179,23 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/serverless-plugin-split-stacks": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/serverless-plugin-split-stacks/-/serverless-plugin-split-stacks-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-VksNqvJUPnGHqef0jHNiN0BzTVr0Hy0cWaLxCG75HiQ3vnIog8qeyiu7uWH6LKNhJnGP1jiTNh0YcheCN8kaKA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"aws-info": "^1.2.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"proxy-agent": "^6.3.1",
|
||||||
|
"semver": "^7.3.5",
|
||||||
|
"throat": "^6.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"serverless": "1 || 2 || 3 || 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/serverless/node_modules/rimraf": {
|
"node_modules/serverless/node_modules/rimraf": {
|
||||||
"version": "5.0.10",
|
"version": "5.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
|
||||||
@@ -14792,7 +15232,6 @@
|
|||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/setprototypeof": {
|
"node_modules/setprototypeof": {
|
||||||
@@ -14923,6 +15362,47 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/smart-buffer": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0",
|
||||||
|
"npm": ">= 3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socks": {
|
||||||
|
"version": "2.8.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
||||||
|
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ip-address": "^10.0.1",
|
||||||
|
"smart-buffer": "^4.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0",
|
||||||
|
"npm": ">= 3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socks-proxy-agent": {
|
||||||
|
"version": "8.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
|
||||||
|
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"socks": "^2.8.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sorted-array-functions": {
|
"node_modules/sorted-array-functions": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
|
||||||
@@ -15504,6 +15984,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/throat": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/through": {
|
"node_modules/through": {
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
@@ -17076,6 +17563,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xml": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/xml-js": {
|
||||||
|
"version": "1.6.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||||
|
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": "^1.2.4"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xml-js": "bin/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xml-js/node_modules/sax": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
|
||||||
|
"license": "BlueOak-1.0.0"
|
||||||
|
},
|
||||||
"node_modules/xml2js": {
|
"node_modules/xml2js": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
||||||
|
|||||||
@@ -97,7 +97,9 @@
|
|||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
|
"serverless-esbuild": "^1.55.1",
|
||||||
"serverless-offline": "^14.4.0",
|
"serverless-offline": "^14.4.0",
|
||||||
|
"serverless-plugin-split-stacks": "^1.14.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "^6.3.4",
|
"supertest": "^6.3.4",
|
||||||
"ts-jest": "^29.1.2",
|
"ts-jest": "^29.1.2",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
binaryTargets = ["native", "rhel-openssl-3.0.x"] // Add Linux target
|
binaryTargets = ["native", "rhel-openssl-3.0.x"] // Lambda Node 18/20 (Amazon Linux) target
|
||||||
previewFeatures = ["multiSchema"]
|
previewFeatures = ["multiSchema"]
|
||||||
|
engineType = "library"
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
@@ -554,20 +555,6 @@ model Frequencies {
|
|||||||
@@schema("mst")
|
@@schema("mst")
|
||||||
}
|
}
|
||||||
|
|
||||||
model NavigationModes {
|
|
||||||
id Int @id @default(autoincrement())
|
|
||||||
navigationModeName String @unique @map("navigation_mode_name") @db.VarChar(30)
|
|
||||||
navigationModeIcon String @map("navigation_mode_icon") @db.VarChar(500)
|
|
||||||
isActive Boolean @default(true) @map("is_active")
|
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
|
||||||
updatedAt DateTime @updatedAt @map("updated_at")
|
|
||||||
deletedAt DateTime? @map("deleted_at")
|
|
||||||
ActivityNavigationModes ActivityNavigationModes[]
|
|
||||||
|
|
||||||
@@map("navigation_modes")
|
|
||||||
@@schema("mst")
|
|
||||||
}
|
|
||||||
|
|
||||||
model TransportModes {
|
model TransportModes {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
transportModeName String @unique @map("transport_mode_name") @db.VarChar(60)
|
transportModeName String @unique @map("transport_mode_name") @db.VarChar(60)
|
||||||
@@ -1052,13 +1039,13 @@ model ActivityOtherDetails {
|
|||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
activityXid Int @map("activity_xid")
|
activityXid Int @map("activity_xid")
|
||||||
activity Activities @relation(fields: [activityXid], references: [id], onDelete: Cascade)
|
activity Activities @relation(fields: [activityXid], references: [id], onDelete: Cascade)
|
||||||
exclusiveNotes String? @map("exclusive_notes") @db.VarChar(500)
|
exclusiveNotes String? @map("exclusive_notes") @db.Text
|
||||||
SafetyInstruction String? @map("safety_instruction") @db.VarChar(400)
|
SafetyInstruction String? @map("safety_instruction") @db.Text
|
||||||
Cancellations String? @map("cancellations") @db.VarChar(400)
|
Cancellations String? @map("cancellations") @db.Text
|
||||||
dosNotes String? @map("dos_notes") @db.VarChar(400)
|
dosNotes String? @map("dos_notes") @db.Text
|
||||||
dontsNotes String? @map("donts_notes") @db.VarChar(400)
|
dontsNotes String? @map("donts_notes") @db.Text
|
||||||
tipsNotes String? @map("tips_notes") @db.VarChar(400)
|
tipsNotes String? @map("tips_notes") @db.Text
|
||||||
termsAndCondition String? @map("terms_and_condition") @db.VarChar(500)
|
termsAndCondition String? @map("terms_and_condition") @db.Text
|
||||||
isActive Boolean @default(true) @map("is_active")
|
isActive Boolean @default(true) @map("is_active")
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
updatedAt DateTime @updatedAt @map("updated_at")
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
@@ -1456,8 +1443,7 @@ model ActivityNavigationModes {
|
|||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
activityXid Int @map("activity_xid")
|
activityXid Int @map("activity_xid")
|
||||||
activity Activities @relation(fields: [activityXid], references: [id], onDelete: Cascade)
|
activity Activities @relation(fields: [activityXid], references: [id], onDelete: Cascade)
|
||||||
navigationModeXid Int @map("navigation_mode_xid")
|
navigationModeName String @map("navigation_mode_name") @db.VarChar(30)
|
||||||
navigationMode NavigationModes @relation(fields: [navigationModeXid], references: [id], onDelete: Restrict)
|
|
||||||
isInActivityChargeable Boolean @default(false) @map("is_in_activity_chargeable")
|
isInActivityChargeable Boolean @default(false) @map("is_in_activity_chargeable")
|
||||||
navigationModesBasePrice Int @map("navigation_modes_base_price")
|
navigationModesBasePrice Int @map("navigation_modes_base_price")
|
||||||
navigationModesTotalPrice Int @map("navigation_modes_total_price")
|
navigationModesTotalPrice Int @map("navigation_modes_total_price")
|
||||||
@@ -1637,8 +1623,8 @@ model Cancellations {
|
|||||||
scheduleHeaderXid Int @map("schedule_header_xid")
|
scheduleHeaderXid Int @map("schedule_header_xid")
|
||||||
scheduleHeader ScheduleHeader @relation(fields: [scheduleHeaderXid], references: [id], onDelete: Cascade)
|
scheduleHeader ScheduleHeader @relation(fields: [scheduleHeaderXid], references: [id], onDelete: Cascade)
|
||||||
occurenceDate DateTime? @map("occurence_date")
|
occurenceDate DateTime? @map("occurence_date")
|
||||||
startTime String? @map("start_time") @db.VarChar(30)
|
startTime String? @map("start_time") @db.VarChar(30)
|
||||||
endTime String? @map("end_time") @db.VarChar(30)
|
endTime String? @map("end_time") @db.VarChar(30)
|
||||||
cancellationReason String? @map("cancellation_reason")
|
cancellationReason String? @map("cancellation_reason")
|
||||||
isActive Boolean @default(true) @map("is_active")
|
isActive Boolean @default(true) @map("is_active")
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
@@ -1742,8 +1728,8 @@ model ItineraryActivities {
|
|||||||
travelMode String? @map("travel_mode") @db.VarChar(30)
|
travelMode String? @map("travel_mode") @db.VarChar(30)
|
||||||
kmForNextPoint Float? @map("km_for_next_point")
|
kmForNextPoint Float? @map("km_for_next_point")
|
||||||
timeForNextPointMins Int? @map("time_for_next_point_mins")
|
timeForNextPointMins Int? @map("time_for_next_point_mins")
|
||||||
paxCount Int @map("pax_count")
|
paxCount Int? @map("pax_count")
|
||||||
totalAmount Int @map("total_amount")
|
totalAmount Int? @map("total_amount")
|
||||||
bookingStatus String @default("pending") @map("booking_status") @db.VarChar(30)
|
bookingStatus String @default("pending") @map("booking_status") @db.VarChar(30)
|
||||||
isActive Boolean @default(true) @map("is_active")
|
isActive Boolean @default(true) @map("is_active")
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
|||||||
@@ -268,9 +268,9 @@ async function main() {
|
|||||||
create: { interestName: 'Nightlife & Events', displayOrder: 10, interestColor: 'Blue', interestImage: 'https://minglar-dev-bucket.s3.ap-south-1.amazonaws.com/StaticImages/InterestTypes/NightlifeandEvents.png', interestCode: 'NE' },
|
create: { interestName: 'Nightlife & Events', displayOrder: 10, interestColor: 'Blue', interestImage: 'https://minglar-dev-bucket.s3.ap-south-1.amazonaws.com/StaticImages/InterestTypes/NightlifeandEvents.png', interestCode: 'NE' },
|
||||||
});
|
});
|
||||||
const furfam = await prisma.interests.upsert({
|
const furfam = await prisma.interests.upsert({
|
||||||
where: { interestName: 'Fur Fam' },
|
where: { interestName: 'Pet space' },
|
||||||
update: {},
|
update: {},
|
||||||
create: { interestName: 'Fur Fam', displayOrder: 11, interestColor: 'Blue', interestImage: 'https://minglar-dev-bucket.s3.ap-south-1.amazonaws.com/StaticImages/InterestTypes/petspace.jpg', interestCode: 'PS' },
|
create: { interestName: 'Pet space', displayOrder: 11, interestColor: 'Blue', interestImage: 'https://minglar-dev-bucket.s3.ap-south-1.amazonaws.com/StaticImages/InterestTypes/petspace.jpg', interestCode: 'PS' },
|
||||||
});
|
});
|
||||||
const dogoodfeelgood = await prisma.interests.upsert({
|
const dogoodfeelgood = await prisma.interests.upsert({
|
||||||
where: { interestName: 'Do Good, Feel Good' },
|
where: { interestName: 'Do Good, Feel Good' },
|
||||||
@@ -693,16 +693,6 @@ async function main() {
|
|||||||
skipDuplicates: true,
|
skipDuplicates: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ✅ Navigation Modes
|
|
||||||
await prisma.navigationModes.createMany({
|
|
||||||
data: [
|
|
||||||
{ navigationModeName: 'Elephant Ride', navigationModeIcon: '🚗' },
|
|
||||||
{ navigationModeName: 'Horse Ride', navigationModeIcon: '🏍️' },
|
|
||||||
{ navigationModeName: 'Camel Ride', navigationModeIcon: '🚶' },
|
|
||||||
],
|
|
||||||
skipDuplicates: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// ✅ Transport Modes
|
// ✅ Transport Modes
|
||||||
await prisma.transportModes.createMany({
|
await prisma.transportModes.createMany({
|
||||||
data: [
|
data: [
|
||||||
|
|||||||
@@ -1,132 +1,13 @@
|
|||||||
service: minglar-host
|
service: minglar-host
|
||||||
|
|
||||||
useDotenv: true
|
useDotenv: ${file(./serverless/common.yml):useDotenv}
|
||||||
|
params: ${file(./serverless/common.yml):params}
|
||||||
params:
|
provider: ${file(./serverless/common.yml):provider}
|
||||||
dev:
|
build: ${file(./serverless/common.yml):build}
|
||||||
stage: dev
|
package: ${file(./serverless/common.yml):package}
|
||||||
test:
|
plugins: ${file(./serverless/common.yml):plugins}
|
||||||
stage: test
|
custom: ${file(./serverless/common.yml):custom}
|
||||||
uat:
|
|
||||||
stage: uat
|
|
||||||
|
|
||||||
provider:
|
|
||||||
name: aws
|
|
||||||
runtime: nodejs22.x
|
|
||||||
region: ap-south-1
|
|
||||||
stage: ${opt:stage, 'dev'}
|
|
||||||
versionFunctions: false
|
|
||||||
memorySize: 512
|
|
||||||
layers:
|
|
||||||
- ${cf:minglar-layers-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
|
||||||
apiGateway:
|
|
||||||
binaryMediaTypes:
|
|
||||||
- '*/*'
|
|
||||||
minimumCompressionSize: 1024
|
|
||||||
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: ${env:DATABASE_URL}
|
|
||||||
DB_USERNAME: ${env:DB_USERNAME}
|
|
||||||
DB_PASSWORD: ${env:DB_PASSWORD}
|
|
||||||
DB_DATABASE_NAME: ${env:DB_DATABASE_NAME}
|
|
||||||
DB_HOSTNAME: ${env:DB_HOSTNAME}
|
|
||||||
DB_PORT: ${env:DB_PORT}
|
|
||||||
BY_PASS_EMAIL: ${env:BY_PASS_EMAIL}
|
|
||||||
BYPASS_OTP: ${env:BYPASS_OTP}
|
|
||||||
BREVO_EMAIL_API_KEY: ${env:BREVO_EMAIL_API_KEY}
|
|
||||||
BREVO_API_BASEURL: ${env:BREVO_API_BASEURL}
|
|
||||||
BREVO_FROM_EMAIL: ${env:BREVO_FROM_EMAIL}
|
|
||||||
BREVO_SMTP_HOST: ${env:BREVO_SMTP_HOST}
|
|
||||||
BREVO_SMTP_PORT: ${env:BREVO_SMTP_PORT}
|
|
||||||
BREVO_SMTP_USER: ${env:BREVO_SMTP_USER}
|
|
||||||
BREVO_SMTP_PASS: ${env:BREVO_SMTP_PASS}
|
|
||||||
REFRESH_TOKEN_SECRET: ${env:REFRESH_TOKEN_SECRET}
|
|
||||||
JWT_SECRET: ${env:JWT_SECRET}
|
|
||||||
JWT_ACCESS_EXPIRATION_MINUTES: ${env:JWT_ACCESS_EXPIRATION_MINUTES}
|
|
||||||
JWT_REFRESH_EXPIRATION_DAYS: ${env:JWT_REFRESH_EXPIRATION_DAYS}
|
|
||||||
JWT_RESET_PASSWORD_EXPIRATION_MINUTES: ${env:JWT_RESET_PASSWORD_EXPIRATION_MINUTES}
|
|
||||||
JWT_VERIFY_EMAIL_EXPIRATION_MINUTES: ${env:JWT_VERIFY_EMAIL_EXPIRATION_MINUTES}
|
|
||||||
SALT_ROUNDS: ${env:SALT_ROUNDS}
|
|
||||||
NODE_ENV: ${env:NODE_ENV}
|
|
||||||
S3_BUCKET_NAME: ${env:S3_BUCKET_NAME}
|
|
||||||
MINGLAR_ADMIN_NAME: ${env:MINGLAR_ADMIN_NAME}
|
|
||||||
MINGLAR_ADMIN_EMAIL: ${env:MINGLAR_ADMIN_EMAIL}
|
|
||||||
AM_INVITATION_LINK: ${env:AM_INVITATION_LINK}
|
|
||||||
HOST_LINK: ${env:HOST_LINK}
|
|
||||||
HOST_LINK_PQ: ${env:HOST_LINK_PQ}
|
|
||||||
|
|
||||||
iam:
|
|
||||||
role:
|
|
||||||
statements:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- s3:PutObject
|
|
||||||
- s3:GetObject
|
|
||||||
- s3:DeleteObject
|
|
||||||
- s3:ListBucket
|
|
||||||
Resource:
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
|
||||||
|
|
||||||
custom:
|
|
||||||
serverless-offline:
|
|
||||||
reloadHandler: true
|
|
||||||
|
|
||||||
build:
|
|
||||||
esbuild:
|
|
||||||
bundle: true
|
|
||||||
minify: true
|
|
||||||
sourcemap: false
|
|
||||||
target: node22
|
|
||||||
platform: node
|
|
||||||
external:
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
exclude:
|
|
||||||
- 'aws-sdk'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '.prisma/client'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- 'pg-*'
|
|
||||||
- 'postgres-*'
|
|
||||||
- 'pgpass'
|
|
||||||
- 'split2'
|
|
||||||
- 'xtend'
|
|
||||||
|
|
||||||
package:
|
|
||||||
individually: true
|
|
||||||
excludeDevDependencies: true
|
|
||||||
patterns:
|
|
||||||
- '!node_modules/**'
|
|
||||||
- '!node_modules/@prisma/**'
|
|
||||||
- '!node_modules/.prisma/**'
|
|
||||||
- '!**/*.test.js'
|
|
||||||
- '!**/*.spec.js'
|
|
||||||
- '!**/test/**'
|
|
||||||
- '!**/__tests__/**'
|
|
||||||
- '!package-lock.json'
|
|
||||||
- '!yarn.lock'
|
|
||||||
- '!README.md'
|
|
||||||
- '!*.config.js'
|
|
||||||
- '!.git/**'
|
|
||||||
- '!.github/**'
|
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
- ${file(./serverless/functions/host.yml)}
|
- ${file(./serverless/functions/host.yml)}
|
||||||
- ${file(./serverless/functions/pqq.yml)}
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
- serverless-offline
|
|
||||||
|
|||||||
13
serverless.minglaradmin.yml
Normal file
13
serverless.minglaradmin.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
service: minglar-admin
|
||||||
|
|
||||||
|
useDotenv: ${file(./serverless/common.yml):useDotenv}
|
||||||
|
params: ${file(./serverless/common.yml):params}
|
||||||
|
provider: ${file(./serverless/common.yml):provider}
|
||||||
|
build: ${file(./serverless/common.yml):build}
|
||||||
|
package: ${file(./serverless/common.yml):package}
|
||||||
|
plugins: ${file(./serverless/common.yml):plugins}
|
||||||
|
custom: ${file(./serverless/common.yml):custom}
|
||||||
|
|
||||||
|
functions:
|
||||||
|
- ${file(./serverless/functions/minglaradmin.yml)}
|
||||||
|
|
||||||
@@ -1,133 +1,13 @@
|
|||||||
service: minglar-prepopulate
|
service: minglar-prepopulate
|
||||||
|
|
||||||
useDotenv: true
|
useDotenv: ${file(./serverless/common.yml):useDotenv}
|
||||||
|
params: ${file(./serverless/common.yml):params}
|
||||||
params:
|
provider: ${file(./serverless/common.yml):provider}
|
||||||
dev:
|
build: ${file(./serverless/common.yml):build}
|
||||||
stage: dev
|
package: ${file(./serverless/common.yml):package}
|
||||||
test:
|
plugins: ${file(./serverless/common.yml):plugins}
|
||||||
stage: test
|
custom: ${file(./serverless/common.yml):custom}
|
||||||
uat:
|
|
||||||
stage: uat
|
|
||||||
|
|
||||||
provider:
|
|
||||||
name: aws
|
|
||||||
runtime: nodejs22.x
|
|
||||||
region: ap-south-1
|
|
||||||
stage: ${opt:stage, 'dev'}
|
|
||||||
versionFunctions: false
|
|
||||||
memorySize: 512
|
|
||||||
layers:
|
|
||||||
- ${cf:minglar-layers-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
|
||||||
httpApi:
|
|
||||||
id: ${cf:minglar-host-${sls:stage}.HttpApiId}
|
|
||||||
apiGateway:
|
|
||||||
binaryMediaTypes:
|
|
||||||
- '*/*'
|
|
||||||
minimumCompressionSize: 1024
|
|
||||||
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: ${env:DATABASE_URL}
|
|
||||||
DB_USERNAME: ${env:DB_USERNAME}
|
|
||||||
DB_PASSWORD: ${env:DB_PASSWORD}
|
|
||||||
DB_DATABASE_NAME: ${env:DB_DATABASE_NAME}
|
|
||||||
DB_HOSTNAME: ${env:DB_HOSTNAME}
|
|
||||||
DB_PORT: ${env:DB_PORT}
|
|
||||||
BY_PASS_EMAIL: ${env:BY_PASS_EMAIL}
|
|
||||||
BYPASS_OTP: ${env:BYPASS_OTP}
|
|
||||||
BREVO_EMAIL_API_KEY: ${env:BREVO_EMAIL_API_KEY}
|
|
||||||
BREVO_API_BASEURL: ${env:BREVO_API_BASEURL}
|
|
||||||
BREVO_FROM_EMAIL: ${env:BREVO_FROM_EMAIL}
|
|
||||||
BREVO_SMTP_HOST: ${env:BREVO_SMTP_HOST}
|
|
||||||
BREVO_SMTP_PORT: ${env:BREVO_SMTP_PORT}
|
|
||||||
BREVO_SMTP_USER: ${env:BREVO_SMTP_USER}
|
|
||||||
BREVO_SMTP_PASS: ${env:BREVO_SMTP_PASS}
|
|
||||||
REFRESH_TOKEN_SECRET: ${env:REFRESH_TOKEN_SECRET}
|
|
||||||
JWT_SECRET: ${env:JWT_SECRET}
|
|
||||||
JWT_ACCESS_EXPIRATION_MINUTES: ${env:JWT_ACCESS_EXPIRATION_MINUTES}
|
|
||||||
JWT_REFRESH_EXPIRATION_DAYS: ${env:JWT_REFRESH_EXPIRATION_DAYS}
|
|
||||||
JWT_RESET_PASSWORD_EXPIRATION_MINUTES: ${env:JWT_RESET_PASSWORD_EXPIRATION_MINUTES}
|
|
||||||
JWT_VERIFY_EMAIL_EXPIRATION_MINUTES: ${env:JWT_VERIFY_EMAIL_EXPIRATION_MINUTES}
|
|
||||||
SALT_ROUNDS: ${env:SALT_ROUNDS}
|
|
||||||
NODE_ENV: ${env:NODE_ENV}
|
|
||||||
S3_BUCKET_NAME: ${env:S3_BUCKET_NAME}
|
|
||||||
MINGLAR_ADMIN_NAME: ${env:MINGLAR_ADMIN_NAME}
|
|
||||||
MINGLAR_ADMIN_EMAIL: ${env:MINGLAR_ADMIN_EMAIL}
|
|
||||||
AM_INVITATION_LINK: ${env:AM_INVITATION_LINK}
|
|
||||||
HOST_LINK: ${env:HOST_LINK}
|
|
||||||
HOST_LINK_PQ: ${env:HOST_LINK_PQ}
|
|
||||||
|
|
||||||
iam:
|
|
||||||
role:
|
|
||||||
statements:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- s3:PutObject
|
|
||||||
- s3:GetObject
|
|
||||||
- s3:DeleteObject
|
|
||||||
- s3:ListBucket
|
|
||||||
Resource:
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
|
||||||
|
|
||||||
custom:
|
|
||||||
serverless-offline:
|
|
||||||
reloadHandler: true
|
|
||||||
|
|
||||||
build:
|
|
||||||
esbuild:
|
|
||||||
bundle: true
|
|
||||||
minify: true
|
|
||||||
sourcemap: false
|
|
||||||
target: node22
|
|
||||||
platform: node
|
|
||||||
external:
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
exclude:
|
|
||||||
- 'aws-sdk'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '.prisma/client'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- 'pg-*'
|
|
||||||
- 'postgres-*'
|
|
||||||
- 'pgpass'
|
|
||||||
- 'split2'
|
|
||||||
- 'xtend'
|
|
||||||
|
|
||||||
package:
|
|
||||||
individually: true
|
|
||||||
excludeDevDependencies: true
|
|
||||||
patterns:
|
|
||||||
- '!node_modules/**'
|
|
||||||
- '!node_modules/@prisma/**'
|
|
||||||
- '!node_modules/.prisma/**'
|
|
||||||
- '!**/*.test.js'
|
|
||||||
- '!**/*.spec.js'
|
|
||||||
- '!**/test/**'
|
|
||||||
- '!**/__tests__/**'
|
|
||||||
- '!package-lock.json'
|
|
||||||
- '!yarn.lock'
|
|
||||||
- '!README.md'
|
|
||||||
- '!*.config.js'
|
|
||||||
- '!.git/**'
|
|
||||||
- '!.github/**'
|
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
- ${file(./serverless/functions/prepopulate.yml)}
|
- ${file(./serverless/functions/prepopulate.yml)}
|
||||||
|
|
||||||
plugins:
|
|
||||||
- serverless-offline
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
service: minglar-layers
|
service: minglar-prisma-layer
|
||||||
|
|
||||||
useDotenv: true
|
useDotenv: true
|
||||||
|
|
||||||
@@ -15,9 +15,13 @@ provider:
|
|||||||
runtime: nodejs22.x
|
runtime: nodejs22.x
|
||||||
region: ap-south-1
|
region: ap-south-1
|
||||||
stage: ${opt:stage, 'dev'}
|
stage: ${opt:stage, 'dev'}
|
||||||
|
deploymentBucket:
|
||||||
|
# use a fixed bucket name to prevent Serverless from creating/quashing a resource
|
||||||
|
name: serverless-framework-deployments-ap-south-1-50264b8e-d2b9
|
||||||
|
# optionally uncomment below to enable serverless to create if missing
|
||||||
|
# serverSideEncryption: AES256
|
||||||
versionFunctions: false
|
versionFunctions: false
|
||||||
|
|
||||||
# Define layers (deployed once; other stacks reference via cf output)
|
|
||||||
layers:
|
layers:
|
||||||
prisma:
|
prisma:
|
||||||
path: layers/prisma
|
path: layers/prisma
|
||||||
@@ -26,5 +30,3 @@ layers:
|
|||||||
compatibleRuntimes:
|
compatibleRuntimes:
|
||||||
- nodejs22.x
|
- nodejs22.x
|
||||||
retain: false
|
retain: false
|
||||||
|
|
||||||
plugins: []
|
|
||||||
@@ -1,133 +1,13 @@
|
|||||||
service: minglar-user
|
service: minglar-user
|
||||||
|
|
||||||
useDotenv: true
|
useDotenv: ${file(./serverless/common.yml):useDotenv}
|
||||||
|
params: ${file(./serverless/common.yml):params}
|
||||||
params:
|
provider: ${file(./serverless/common.yml):provider}
|
||||||
dev:
|
build: ${file(./serverless/common.yml):build}
|
||||||
stage: dev
|
package: ${file(./serverless/common.yml):package}
|
||||||
test:
|
plugins: ${file(./serverless/common.yml):plugins}
|
||||||
stage: test
|
custom: ${file(./serverless/common.yml):custom}
|
||||||
uat:
|
|
||||||
stage: uat
|
|
||||||
|
|
||||||
provider:
|
|
||||||
name: aws
|
|
||||||
runtime: nodejs22.x
|
|
||||||
region: ap-south-1
|
|
||||||
stage: ${opt:stage, 'dev'}
|
|
||||||
versionFunctions: false
|
|
||||||
memorySize: 512
|
|
||||||
layers:
|
|
||||||
- ${cf:minglar-layers-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
|
||||||
httpApi:
|
|
||||||
id: ${cf:minglar-host-${sls:stage}.HttpApiId}
|
|
||||||
apiGateway:
|
|
||||||
binaryMediaTypes:
|
|
||||||
- '*/*'
|
|
||||||
minimumCompressionSize: 1024
|
|
||||||
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: ${env:DATABASE_URL}
|
|
||||||
DB_USERNAME: ${env:DB_USERNAME}
|
|
||||||
DB_PASSWORD: ${env:DB_PASSWORD}
|
|
||||||
DB_DATABASE_NAME: ${env:DB_DATABASE_NAME}
|
|
||||||
DB_HOSTNAME: ${env:DB_HOSTNAME}
|
|
||||||
DB_PORT: ${env:DB_PORT}
|
|
||||||
BY_PASS_EMAIL: ${env:BY_PASS_EMAIL}
|
|
||||||
BYPASS_OTP: ${env:BYPASS_OTP}
|
|
||||||
BREVO_EMAIL_API_KEY: ${env:BREVO_EMAIL_API_KEY}
|
|
||||||
BREVO_API_BASEURL: ${env:BREVO_API_BASEURL}
|
|
||||||
BREVO_FROM_EMAIL: ${env:BREVO_FROM_EMAIL}
|
|
||||||
BREVO_SMTP_HOST: ${env:BREVO_SMTP_HOST}
|
|
||||||
BREVO_SMTP_PORT: ${env:BREVO_SMTP_PORT}
|
|
||||||
BREVO_SMTP_USER: ${env:BREVO_SMTP_USER}
|
|
||||||
BREVO_SMTP_PASS: ${env:BREVO_SMTP_PASS}
|
|
||||||
REFRESH_TOKEN_SECRET: ${env:REFRESH_TOKEN_SECRET}
|
|
||||||
JWT_SECRET: ${env:JWT_SECRET}
|
|
||||||
JWT_ACCESS_EXPIRATION_MINUTES: ${env:JWT_ACCESS_EXPIRATION_MINUTES}
|
|
||||||
JWT_REFRESH_EXPIRATION_DAYS: ${env:JWT_REFRESH_EXPIRATION_DAYS}
|
|
||||||
JWT_RESET_PASSWORD_EXPIRATION_MINUTES: ${env:JWT_RESET_PASSWORD_EXPIRATION_MINUTES}
|
|
||||||
JWT_VERIFY_EMAIL_EXPIRATION_MINUTES: ${env:JWT_VERIFY_EMAIL_EXPIRATION_MINUTES}
|
|
||||||
SALT_ROUNDS: ${env:SALT_ROUNDS}
|
|
||||||
NODE_ENV: ${env:NODE_ENV}
|
|
||||||
S3_BUCKET_NAME: ${env:S3_BUCKET_NAME}
|
|
||||||
MINGLAR_ADMIN_NAME: ${env:MINGLAR_ADMIN_NAME}
|
|
||||||
MINGLAR_ADMIN_EMAIL: ${env:MINGLAR_ADMIN_EMAIL}
|
|
||||||
AM_INVITATION_LINK: ${env:AM_INVITATION_LINK}
|
|
||||||
HOST_LINK: ${env:HOST_LINK}
|
|
||||||
HOST_LINK_PQ: ${env:HOST_LINK_PQ}
|
|
||||||
|
|
||||||
iam:
|
|
||||||
role:
|
|
||||||
statements:
|
|
||||||
- Effect: Allow
|
|
||||||
Action:
|
|
||||||
- s3:PutObject
|
|
||||||
- s3:GetObject
|
|
||||||
- s3:DeleteObject
|
|
||||||
- s3:ListBucket
|
|
||||||
Resource:
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
|
||||||
|
|
||||||
custom:
|
|
||||||
serverless-offline:
|
|
||||||
reloadHandler: true
|
|
||||||
|
|
||||||
build:
|
|
||||||
esbuild:
|
|
||||||
bundle: true
|
|
||||||
minify: true
|
|
||||||
sourcemap: false
|
|
||||||
target: node22
|
|
||||||
platform: node
|
|
||||||
external:
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
exclude:
|
|
||||||
- 'aws-sdk'
|
|
||||||
- '@aws-sdk/*'
|
|
||||||
- '@smithy/*'
|
|
||||||
- '@aws-crypto/*'
|
|
||||||
- '@prisma/adapter-pg'
|
|
||||||
- '@prisma/client'
|
|
||||||
- '.prisma'
|
|
||||||
- '.prisma/client'
|
|
||||||
- 'pg'
|
|
||||||
- 'zod'
|
|
||||||
- 'pg-*'
|
|
||||||
- 'postgres-*'
|
|
||||||
- 'pgpass'
|
|
||||||
- 'split2'
|
|
||||||
- 'xtend'
|
|
||||||
|
|
||||||
package:
|
|
||||||
individually: true
|
|
||||||
excludeDevDependencies: true
|
|
||||||
patterns:
|
|
||||||
- '!node_modules/**'
|
|
||||||
- '!node_modules/@prisma/**'
|
|
||||||
- '!node_modules/.prisma/**'
|
|
||||||
- '!**/*.test.js'
|
|
||||||
- '!**/*.spec.js'
|
|
||||||
- '!**/test/**'
|
|
||||||
- '!**/__tests__/**'
|
|
||||||
- '!package-lock.json'
|
|
||||||
- '!yarn.lock'
|
|
||||||
- '!README.md'
|
|
||||||
- '!*.config.js'
|
|
||||||
- '!.git/**'
|
|
||||||
- '!.github/**'
|
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
- ${file(./serverless/functions/user.yml)}
|
- ${file(./serverless/functions/user.yml)}
|
||||||
|
|
||||||
plugins:
|
|
||||||
- serverless-offline
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# Legacy monolith config. For new deployments use serverless.*.yml files.
|
||||||
service: minglar
|
service: minglar
|
||||||
|
|
||||||
|
|
||||||
@@ -16,6 +17,11 @@ provider:
|
|||||||
runtime: nodejs22.x
|
runtime: nodejs22.x
|
||||||
region: ap-south-1
|
region: ap-south-1
|
||||||
stage: ${opt:stage, 'dev'}
|
stage: ${opt:stage, 'dev'}
|
||||||
|
deploymentBucket:
|
||||||
|
# use a fixed bucket name to prevent Serverless from creating/quashing a resource
|
||||||
|
name: serverless-framework-deployments-ap-south-1-50264b8e-d2b9
|
||||||
|
# optionally uncomment below to enable serverless to create if missing
|
||||||
|
# serverSideEncryption: AES256
|
||||||
versionFunctions: false
|
versionFunctions: false
|
||||||
memorySize: 512
|
memorySize: 512
|
||||||
# Apply Prisma layer to all functions
|
# Apply Prisma layer to all functions
|
||||||
@@ -23,7 +29,7 @@ provider:
|
|||||||
layers:
|
layers:
|
||||||
# Use the exported stack output so deploy function works (expects a string ARN)
|
# Use the exported stack output so deploy function works (expects a string ARN)
|
||||||
# For offline/local, fall back to an empty string so the CF lookup is optional.
|
# For offline/local, fall back to an empty string so the CF lookup is optional.
|
||||||
- ${cf:${self:service}-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
- ${cf:${self:service}-${sls:stage}.PrismaLambdaLayerQualifiedArn, ''}
|
||||||
apiGateway:
|
apiGateway:
|
||||||
binaryMediaTypes:
|
binaryMediaTypes:
|
||||||
- '*/*'
|
- '*/*'
|
||||||
@@ -73,16 +79,12 @@ provider:
|
|||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
||||||
|
|
||||||
custom:
|
|
||||||
serverless-offline:
|
|
||||||
reloadHandler: true
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
esbuild:
|
esbuild:
|
||||||
bundle: true
|
bundle: true
|
||||||
minify: true
|
minify: true
|
||||||
sourcemap: false
|
sourcemap: false
|
||||||
target: node22
|
target: node20
|
||||||
platform: node
|
platform: node
|
||||||
# Mark as external so they're not bundled into the JS
|
# Mark as external so they're not bundled into the JS
|
||||||
external:
|
external:
|
||||||
@@ -125,7 +127,6 @@ layers:
|
|||||||
|
|
||||||
package:
|
package:
|
||||||
individually: true
|
individually: true
|
||||||
excludeDevDependencies: true
|
|
||||||
patterns:
|
patterns:
|
||||||
- '!node_modules/**'
|
- '!node_modules/**'
|
||||||
- '!node_modules/@prisma/**'
|
- '!node_modules/@prisma/**'
|
||||||
@@ -146,8 +147,18 @@ functions:
|
|||||||
- ${file(./serverless/functions/host.yml)}
|
- ${file(./serverless/functions/host.yml)}
|
||||||
- ${file(./serverless/functions/minglaradmin.yml)}
|
- ${file(./serverless/functions/minglaradmin.yml)}
|
||||||
- ${file(./serverless/functions/prepopulate.yml)}
|
- ${file(./serverless/functions/prepopulate.yml)}
|
||||||
- ${file(./serverless/functions/pqq.yml)}
|
|
||||||
- ${file(./serverless/functions/user.yml)}
|
- ${file(./serverless/functions/user.yml)}
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- serverless-offline
|
- serverless-offline
|
||||||
|
- serverless-plugin-split-stacks
|
||||||
|
|
||||||
|
custom:
|
||||||
|
serverless-offline:
|
||||||
|
reloadHandler: true
|
||||||
|
|
||||||
|
# split-stacks configuration to avoid CloudFormation resource limit
|
||||||
|
splitStacks:
|
||||||
|
perFunction: true
|
||||||
|
perType: true
|
||||||
|
perGroupFunction: false
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
service: minglar-admin
|
|
||||||
|
|
||||||
useDotenv: true
|
useDotenv: true
|
||||||
|
|
||||||
params:
|
params:
|
||||||
@@ -15,12 +13,17 @@ provider:
|
|||||||
runtime: nodejs22.x
|
runtime: nodejs22.x
|
||||||
region: ap-south-1
|
region: ap-south-1
|
||||||
stage: ${opt:stage, 'dev'}
|
stage: ${opt:stage, 'dev'}
|
||||||
|
deploymentBucket:
|
||||||
|
# use a fixed bucket name to prevent Serverless from creating/quashing a resource
|
||||||
|
name: serverless-framework-deployments-ap-south-1-50264b8e-d2b9
|
||||||
|
# optionally uncomment below to enable serverless to create if missing
|
||||||
|
# serverSideEncryption: AES256
|
||||||
versionFunctions: false
|
versionFunctions: false
|
||||||
memorySize: 512
|
memorySize: 512
|
||||||
|
# Apply Prisma layer to all functions
|
||||||
|
# Reference the layer defined in the dedicated layer stack
|
||||||
layers:
|
layers:
|
||||||
- ${cf:minglar-layers-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
- ${cf:minglar-prisma-layer-${sls:stage}.PrismaLambdaLayerQualifiedArn}
|
||||||
httpApi:
|
|
||||||
id: ${cf:minglar-host-${sls:stage}.HttpApiId}
|
|
||||||
apiGateway:
|
apiGateway:
|
||||||
binaryMediaTypes:
|
binaryMediaTypes:
|
||||||
- '*/*'
|
- '*/*'
|
||||||
@@ -70,17 +73,14 @@ provider:
|
|||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}'
|
||||||
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
- 'arn:aws:s3:::${env:S3_BUCKET_NAME}/*'
|
||||||
|
|
||||||
custom:
|
|
||||||
serverless-offline:
|
|
||||||
reloadHandler: true
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
esbuild:
|
esbuild:
|
||||||
bundle: true
|
bundle: true
|
||||||
minify: true
|
minify: true
|
||||||
sourcemap: false
|
sourcemap: false
|
||||||
target: node22
|
target: node20
|
||||||
platform: node
|
platform: node
|
||||||
|
# Mark as external so they're not bundled into the JS
|
||||||
external:
|
external:
|
||||||
- '@prisma/client'
|
- '@prisma/client'
|
||||||
- '.prisma/client'
|
- '.prisma/client'
|
||||||
@@ -91,6 +91,7 @@ build:
|
|||||||
- '@aws-sdk/*'
|
- '@aws-sdk/*'
|
||||||
- '@smithy/*'
|
- '@smithy/*'
|
||||||
- '@aws-crypto/*'
|
- '@aws-crypto/*'
|
||||||
|
# Exclude prevents npm install of these packages in the zip
|
||||||
exclude:
|
exclude:
|
||||||
- 'aws-sdk'
|
- 'aws-sdk'
|
||||||
- '@aws-sdk/*'
|
- '@aws-sdk/*'
|
||||||
@@ -110,7 +111,6 @@ build:
|
|||||||
|
|
||||||
package:
|
package:
|
||||||
individually: true
|
individually: true
|
||||||
excludeDevDependencies: true
|
|
||||||
patterns:
|
patterns:
|
||||||
- '!node_modules/**'
|
- '!node_modules/**'
|
||||||
- '!node_modules/@prisma/**'
|
- '!node_modules/@prisma/**'
|
||||||
@@ -126,8 +126,9 @@ package:
|
|||||||
- '!.git/**'
|
- '!.git/**'
|
||||||
- '!.github/**'
|
- '!.github/**'
|
||||||
|
|
||||||
functions:
|
|
||||||
- ${file(./serverless/functions/minglaradmin.yml)}
|
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- serverless-offline
|
- serverless-offline
|
||||||
|
|
||||||
|
custom:
|
||||||
|
serverless-offline:
|
||||||
|
reloadHandler: true
|
||||||
@@ -14,7 +14,7 @@ getHosts:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host
|
path: /
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
verifyOTP:
|
verifyOTP:
|
||||||
@@ -30,7 +30,7 @@ verifyOTP:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/verify-otp
|
path: /Host_Admin/onboarding/verify-otp
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
login:
|
login:
|
||||||
@@ -46,7 +46,7 @@ login:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/login
|
path: /Host_Admin/onboarding/login
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
signUp:
|
signUp:
|
||||||
@@ -62,7 +62,7 @@ signUp:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/registration
|
path: /Host_Admin/onboarding/registration
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
createPassword:
|
createPassword:
|
||||||
@@ -78,7 +78,7 @@ createPassword:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/create-password
|
path: /Host_Admin/onboarding/create-password
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
updateBankDetails:
|
updateBankDetails:
|
||||||
@@ -94,7 +94,7 @@ updateBankDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/add-payment-details
|
path: /Host_Admin/onboarding/add-payment-details
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
saveActivity_ForPQQ:
|
saveActivity_ForPQQ:
|
||||||
@@ -110,7 +110,7 @@ saveActivity_ForPQQ:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/add-activity
|
path: /Activity_Hub/OnBoarding/add-activity
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
getHostById:
|
getHostById:
|
||||||
@@ -126,7 +126,7 @@ getHostById:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/getById
|
path: /getById
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getPQQ_ByQuestionId:
|
getPQQ_ByQuestionId:
|
||||||
@@ -142,7 +142,7 @@ getPQQ_ByQuestionId:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/get-pqq-question-details
|
path: /Activity_Hub/OnBoarding/get-pqq-question-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getPQQ_LastUpdatedQuestion:
|
getPQQ_LastUpdatedQuestion:
|
||||||
@@ -158,7 +158,7 @@ getPQQ_LastUpdatedQuestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/get-latest-pqq-question-details
|
path: /Activity_Hub/OnBoarding/get-latest-pqq-question-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
prePopulateNewActivity:
|
prePopulateNewActivity:
|
||||||
@@ -174,7 +174,7 @@ prePopulateNewActivity:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/prepopulate-new-activity
|
path: /Activity_Hub/OnBoarding/prepopulate-new-activity
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
createNewActivity:
|
createNewActivity:
|
||||||
@@ -191,7 +191,7 @@ createNewActivity:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/create-new-activity
|
path: /Activity_Hub/OnBoarding/create-new-activity
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
showSuggestion:
|
showSuggestion:
|
||||||
@@ -207,7 +207,7 @@ showSuggestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/get-suggestion
|
path: /get-suggestion
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllActivitySuggestion:
|
getAllActivitySuggestion:
|
||||||
@@ -223,7 +223,7 @@ getAllActivitySuggestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/get-Activity-suggestion
|
path: /get-Activity-suggestion
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllHostActivity:
|
getAllHostActivity:
|
||||||
@@ -239,7 +239,7 @@ getAllHostActivity:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/get-all-host-activity
|
path: /Activity_Hub/OnBoarding/get-all-host-activity
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
acceptAggrement:
|
acceptAggrement:
|
||||||
@@ -255,9 +255,25 @@ acceptAggrement:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/accept-agreement
|
path: /Host_Admin/onboarding/accept-agreement
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
|
getLatestAgreement:
|
||||||
|
handler: src/modules/host/handlers/Host_Admin/onboarding/getLatestAgreement.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/host/handlers/Host_Admin/onboarding/getLatestAgreement.*'
|
||||||
|
- 'src/modules/host/services/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /Host_Admin/onboarding/get-latest-agreement
|
||||||
|
method: get
|
||||||
|
|
||||||
getStepperInfo:
|
getStepperInfo:
|
||||||
handler: src/modules/host/handlers/getStepper.handler
|
handler: src/modules/host/handlers/getStepper.handler
|
||||||
memorySize: 384
|
memorySize: 384
|
||||||
@@ -276,6 +292,22 @@ getStepperInfo:
|
|||||||
path: /stepper
|
path: /stepper
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
|
updateHostProfile:
|
||||||
|
handler: src/modules/host/handlers/updateHostProfile.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/host/handlers/updateHostProfile.*'
|
||||||
|
- 'src/modules/host/services/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /profile
|
||||||
|
method: patch
|
||||||
|
|
||||||
# Functions with S3/AWS SDK dependencies
|
# Functions with S3/AWS SDK dependencies
|
||||||
submitCompanyDetails:
|
submitCompanyDetails:
|
||||||
handler: src/modules/host/handlers/Host_Admin/onboarding/submitCompanyDetails.handler
|
handler: src/modules/host/handlers/Host_Admin/onboarding/submitCompanyDetails.handler
|
||||||
@@ -288,7 +320,7 @@ submitCompanyDetails:
|
|||||||
- 'src/common/**'
|
- 'src/common/**'
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Host_Admin/onboarding/add-company-details
|
path: /Host_Admin/onboarding/add-company-details
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
submitPQQ_Answer:
|
submitPQQ_Answer:
|
||||||
@@ -304,7 +336,7 @@ submitPQQ_Answer:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/submit-pqq-answer
|
path: /Activity_Hub/OnBoarding/submit-pqq-answer
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
updatePQQ_LastAnswer:
|
updatePQQ_LastAnswer:
|
||||||
@@ -320,7 +352,7 @@ updatePQQ_LastAnswer:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/submit-final-pqq-answer
|
path: /Activity_Hub/OnBoarding/submit-final-pqq-answer
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
submitPQQForReview:
|
submitPQQForReview:
|
||||||
@@ -336,7 +368,7 @@ submitPQQForReview:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/submit-pqq-for-review
|
path: /Activity_Hub/OnBoarding/submit-pqq-for-review
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
getAllPQQwithSubmittedAns:
|
getAllPQQwithSubmittedAns:
|
||||||
@@ -351,7 +383,7 @@ getAllPQQwithSubmittedAns:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/get-all-pqq-ques-submited-ans
|
path: /Activity_Hub/OnBoarding/get-all-pqq-ques-submited-ans
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllDetailsOfActivityAndVenue:
|
getAllDetailsOfActivityAndVenue:
|
||||||
@@ -366,7 +398,7 @@ getAllDetailsOfActivityAndVenue:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/get-all-details-activity-venue/{activityXid}
|
path: /Activity_Hub/OnBoarding/get-all-details-activity-venue/{activityXid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
updateSuggestionAsReviewed:
|
updateSuggestionAsReviewed:
|
||||||
@@ -381,7 +413,7 @@ updateSuggestionAsReviewed:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /host/Activity_Hub/OnBoarding/update-suggestion-reviewed
|
path: /Activity_Hub/OnBoarding/update-suggestion-reviewed
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
resendOTPmail:
|
resendOTPmail:
|
||||||
@@ -522,4 +554,34 @@ openCanceledSlotForActivity:
|
|||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /scheduling/open-canceled-slot
|
path: /scheduling/open-canceled-slot
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
|
createActivityAndAllQuestionsEntry:
|
||||||
|
handler: src/modules/host/handlers/Activity_Hub/OnBoarding/createActivityAndAllQuestionsEntry.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/host/handlers/Activity_Hub/OnBoarding/createActivityAndAllQuestionsEntry**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /Activity_Hub/OnBoarding/create-activity
|
||||||
|
method: post
|
||||||
|
|
||||||
|
submitPQAnswer:
|
||||||
|
handler: src/modules/host/handlers/Activity_Hub/OnBoarding/submitPQAnswer.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/host/handlers/Activity_Hub/OnBoarding/submitPQAnswer**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /Activity_Hub/OnBoarding/submit-pq-answer
|
||||||
|
method: patch
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ minglarRegistration:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/registration
|
path: /registration
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
minglarLoginForAdmin:
|
minglarLoginForAdmin:
|
||||||
@@ -28,7 +28,7 @@ minglarLoginForAdmin:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/login
|
path: /login
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
minglarCreatePassword:
|
minglarCreatePassword:
|
||||||
@@ -43,7 +43,7 @@ minglarCreatePassword:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/create-password
|
path: /create-password
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
updateMinglarProfile:
|
updateMinglarProfile:
|
||||||
@@ -60,7 +60,7 @@ updateMinglarProfile:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/update-profile
|
path: /update-profile
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
prepopulateRole:
|
prepopulateRole:
|
||||||
@@ -75,7 +75,7 @@ prepopulateRole:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/prepopulate-Roles
|
path: /prepopulate-Roles
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getHostDetailsById:
|
getHostDetailsById:
|
||||||
@@ -90,7 +90,7 @@ getHostDetailsById:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/get-host-details/{host_xid}
|
path: /hosthub/hosts/get-host-details/{host_xid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
inviteTeammate:
|
inviteTeammate:
|
||||||
@@ -105,7 +105,7 @@ inviteTeammate:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/settings/teammates/invite-teammate
|
path: /settings/teammates/invite-teammate
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
getAllHostApplication:
|
getAllHostApplication:
|
||||||
@@ -121,7 +121,7 @@ getAllHostApplication:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/get-all-host-applications-am
|
path: /hosthub/hosts/get-all-host-applications-am
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllHostActivityForAdmin:
|
getAllHostActivityForAdmin:
|
||||||
@@ -137,7 +137,7 @@ getAllHostActivityForAdmin:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/get-all-activity-of-host/{id}
|
path: /get-all-activity-of-host/{id}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllOnboardingHostApplications:
|
getAllOnboardingHostApplications:
|
||||||
@@ -153,7 +153,7 @@ getAllOnboardingHostApplications:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/get-all-host-applications-admin
|
path: /hosthub/onboarding/get-all-host-applications-admin
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllOnboardingHostApplications_New:
|
getAllOnboardingHostApplications_New:
|
||||||
@@ -169,7 +169,7 @@ getAllOnboardingHostApplications_New:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/get-all-host-applications-admin-new
|
path: /hosthub/onboarding/get-all-host-applications-admin-new
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllInvitationDetails:
|
getAllInvitationDetails:
|
||||||
@@ -184,7 +184,7 @@ getAllInvitationDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/settings/teammates/get-all-invitation-details
|
path: /settings/teammates/get-all-invitation-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
addSuggestion:
|
addSuggestion:
|
||||||
@@ -200,7 +200,7 @@ addSuggestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/add-suggestion
|
path: /hosthub/hosts/add-suggestion
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
getAllCoadminAndAMDetails:
|
getAllCoadminAndAMDetails:
|
||||||
@@ -215,7 +215,7 @@ getAllCoadminAndAMDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/settings/teammates/get-all-coadmin-am
|
path: /settings/teammates/get-all-coadmin-am
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllInvitedCoadminAndAMDetails:
|
getAllInvitedCoadminAndAMDetails:
|
||||||
@@ -230,7 +230,7 @@ getAllInvitedCoadminAndAMDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/settings/teammates/get-all-invited-coadmin-am
|
path: /settings/teammates/get-all-invited-coadmin-am
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAmDetailsbyId:
|
getAmDetailsbyId:
|
||||||
@@ -245,7 +245,7 @@ getAmDetailsbyId:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/settings/teammates/get-am-details-by-id/{amXid}
|
path: /settings/teammates/get-am-details-by-id/{amXid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
assignAMToHost:
|
assignAMToHost:
|
||||||
@@ -261,7 +261,7 @@ assignAMToHost:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/assign-am
|
path: /hosthub/onboarding/assign-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
editAgreementDetailsAndAccept:
|
editAgreementDetailsAndAccept:
|
||||||
@@ -277,7 +277,7 @@ editAgreementDetailsAndAccept:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/edit-agreement-accept-host
|
path: /hosthub/onboarding/edit-agreement-accept-host
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
getAllPqqQuesAnsForAM:
|
getAllPqqQuesAnsForAM:
|
||||||
@@ -292,7 +292,7 @@ getAllPqqQuesAnsForAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/get-all-pqq-ques-ans-for-am
|
path: /hosthub/onboarding/get-all-pqq-ques-ans-for-am
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
acceptHostApplication:
|
acceptHostApplication:
|
||||||
@@ -308,7 +308,7 @@ acceptHostApplication:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/accept-host-application
|
path: /hosthub/hosts/accept-host-application
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
RejectPQQByAM:
|
RejectPQQByAM:
|
||||||
@@ -324,7 +324,7 @@ RejectPQQByAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/reject-pq-by-am
|
path: /hosthub/hosts/reject-pq-by-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
rejectActivityDetailsApplicationByAM:
|
rejectActivityDetailsApplicationByAM:
|
||||||
@@ -340,7 +340,7 @@ rejectActivityDetailsApplicationByAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/reject-activity-application-by-am
|
path: /hosthub/hosts/reject-activity-application-by-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
acceptPQByAM:
|
acceptPQByAM:
|
||||||
@@ -356,7 +356,7 @@ acceptPQByAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/accept-pq-by-am
|
path: /hosthub/hosts/accept-pq-by-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
acceptActivityDetailsApplicationByAM:
|
acceptActivityDetailsApplicationByAM:
|
||||||
@@ -372,7 +372,7 @@ acceptActivityDetailsApplicationByAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/accept-activity-application-by-am
|
path: /hosthub/hosts/accept-activity-application-by-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
rejectHostApplication:
|
rejectHostApplication:
|
||||||
@@ -388,7 +388,7 @@ rejectHostApplication:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/reject-host-application
|
path: /hosthub/onboarding/reject-host-application
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
rejectHostApplicationAM:
|
rejectHostApplicationAM:
|
||||||
@@ -404,7 +404,7 @@ rejectHostApplicationAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/reject-host-application-am
|
path: /hosthub/hosts/reject-host-application-am
|
||||||
method: patch
|
method: patch
|
||||||
|
|
||||||
addPQQSuggestion:
|
addPQQSuggestion:
|
||||||
@@ -420,7 +420,7 @@ addPQQSuggestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/add-Pqq-suggestion
|
path: /hosthub/hosts/add-Pqq-suggestion
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
addActivitySuggestion:
|
addActivitySuggestion:
|
||||||
@@ -436,7 +436,7 @@ addActivitySuggestion:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/hosts/add-Activity-suggestion
|
path: /hosthub/hosts/add-Activity-suggestion
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
getAllPQPDetailsForAM:
|
getAllPQPDetailsForAM:
|
||||||
@@ -452,7 +452,7 @@ getAllPQPDetailsForAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/pqp/pqp-details-for-am/{activityXid}
|
path: /hosthub/pqp/pqp-details-for-am/{activityXid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getSuggestionsForAM:
|
getSuggestionsForAM:
|
||||||
@@ -468,5 +468,5 @@ getSuggestionsForAM:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /minglaradmin/hosthub/onboarding/show-suggestion-to-am/{hostXid}
|
path: /hosthub/onboarding/show-suggestion-to-am/{hostXid}
|
||||||
method: get
|
method: get
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
createActivityAndAllQuestionsEntry:
|
|
||||||
handler: src/modules/host/handlers/Activity_Hub/OnBoarding/createActivityAndAllQuestionsEntry.handler
|
|
||||||
memorySize: 384
|
|
||||||
package:
|
|
||||||
patterns:
|
|
||||||
- 'src/modules/host/handlers/Activity_Hub/OnBoarding/createActivityAndAllQuestionsEntry**'
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern1}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern2}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern3}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
|
||||||
events:
|
|
||||||
- httpApi:
|
|
||||||
path: /host/Activity_Hub/OnBoarding/create-activity
|
|
||||||
method: post
|
|
||||||
|
|
||||||
submitPQAnswer:
|
|
||||||
handler: src/modules/host/handlers/Activity_Hub/OnBoarding/submitPQAnswer.handler
|
|
||||||
memorySize: 384
|
|
||||||
package:
|
|
||||||
patterns:
|
|
||||||
- 'src/modules/host/handlers/Activity_Hub/OnBoarding/submitPQAnswer**'
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern1}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern2}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern3}
|
|
||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
|
||||||
events:
|
|
||||||
- httpApi:
|
|
||||||
path: /host/Activity_Hub/OnBoarding/submit-pq-answer
|
|
||||||
method: patch
|
|
||||||
@@ -13,7 +13,7 @@ getAllBankAndCurrencyDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-all-bank-currency-details
|
path: /get-all-bank-currency-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getCityByState:
|
getCityByState:
|
||||||
@@ -29,7 +29,7 @@ getCityByState:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-city-by-state
|
path: /get-city-by-state
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getBranchByBankXid:
|
getBranchByBankXid:
|
||||||
@@ -45,7 +45,7 @@ getBranchByBankXid:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-branch-by-bank
|
path: /get-branch-by-bank
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllDocumentCountryStateCityDetails:
|
getAllDocumentCountryStateCityDetails:
|
||||||
@@ -60,7 +60,7 @@ getAllDocumentCountryStateCityDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-all-doc-country
|
path: /get-all-doc-country
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAllPqqQuesAns:
|
getAllPqqQuesAns:
|
||||||
@@ -75,7 +75,7 @@ getAllPqqQuesAns:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-all-pqq-ques-ans
|
path: /get-all-pqq-ques-ans
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getFrequenciesOfActivity:
|
getFrequenciesOfActivity:
|
||||||
@@ -90,7 +90,7 @@ getFrequenciesOfActivity:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-all-Frequencies
|
path: /get-all-Frequencies
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getAddActivityPrePopulate:
|
getAddActivityPrePopulate:
|
||||||
@@ -105,5 +105,5 @@ getAddActivityPrePopulate:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /prepopulate/get-add-activity-prepopulate
|
path: /get-add-activity-prepopulate
|
||||||
method: get
|
method: get
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ registerUser:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/register
|
path: /register
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
submitPersonalInfo:
|
submitPersonalInfo:
|
||||||
@@ -28,7 +28,7 @@ submitPersonalInfo:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/submit-personal-info
|
path: /submit-personal-info
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
verifyOtpForUser:
|
verifyOtpForUser:
|
||||||
@@ -43,7 +43,7 @@ verifyOtpForUser:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/verify-otp
|
path: /verify-otp
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
generateAccessFromRefreshToken:
|
generateAccessFromRefreshToken:
|
||||||
@@ -58,7 +58,7 @@ generateAccessFromRefreshToken:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/generate-access-from-refresh
|
path: /generate-access-from-refresh
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ setPasscodeForMobile:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/set-passcode
|
path: /set-passcode
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ verifyPasscode:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/verify-passcode
|
path: /verify-passcode
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
setUserInterest:
|
setUserInterest:
|
||||||
@@ -105,7 +105,7 @@ setUserInterest:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/set-interests
|
path: /set-interests
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
setUserLocationss:
|
setUserLocationss:
|
||||||
@@ -120,7 +120,7 @@ setUserLocationss:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/set-location-user
|
path: /set-location-user
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
getLandingPageDetails:
|
getLandingPageDetails:
|
||||||
@@ -135,7 +135,7 @@ getLandingPageDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/get-landing-page-details
|
path: /activities/get-landing-page-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getSurpriseMePageDetails:
|
getSurpriseMePageDetails:
|
||||||
@@ -150,7 +150,7 @@ getSurpriseMePageDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/get-surprise-me-page-details
|
path: /activities/get-surprise-me-page-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getActivityDetailsById:
|
getActivityDetailsById:
|
||||||
@@ -165,7 +165,7 @@ getActivityDetailsById:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/get-activity-details-by-id/{activity_xid}
|
path: /activities/get-activity-details-by-id/{activity_xid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
checkAvailabilityDetails:
|
checkAvailabilityDetails:
|
||||||
@@ -180,7 +180,7 @@ checkAvailabilityDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/check-availability/{activity_xid}
|
path: /activities/check-availability/{activity_xid}
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
searchActivities:
|
searchActivities:
|
||||||
@@ -195,7 +195,7 @@ searchActivities:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/specific-search
|
path: /activities/specific-search
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
searchSchoolsAndCompanies:
|
searchSchoolsAndCompanies:
|
||||||
@@ -210,7 +210,7 @@ searchSchoolsAndCompanies:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/search-schools-companies
|
path: /connections/search-schools-companies
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
searchCities:
|
searchCities:
|
||||||
@@ -225,7 +225,7 @@ searchCities:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/search-cities
|
path: /connections/search-cities
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
addSchoolCompanyDetail:
|
addSchoolCompanyDetail:
|
||||||
@@ -240,7 +240,7 @@ addSchoolCompanyDetail:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/add-school-company
|
path: /connections/add-school-company
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
removeConnectionDetails:
|
removeConnectionDetails:
|
||||||
@@ -255,7 +255,7 @@ removeConnectionDetails:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/remove-connection-details
|
path: /connections/remove-connection-details
|
||||||
method: delete
|
method: delete
|
||||||
|
|
||||||
getAllConnectionOfUser:
|
getAllConnectionOfUser:
|
||||||
@@ -270,7 +270,7 @@ getAllConnectionOfUser:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/get-all-connections-details
|
path: /connections/get-all-connections-details
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getActivityFromConnectionsInterest:
|
getActivityFromConnectionsInterest:
|
||||||
@@ -285,7 +285,22 @@ getActivityFromConnectionsInterest:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/connections/get-activity-from-connections-interest
|
path: /connections/get-activity-from-connections-interest
|
||||||
|
method: get
|
||||||
|
|
||||||
|
searchConnectionPeople:
|
||||||
|
handler: src/modules/user/handlers/connections/searchConnectionPeople.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/handlers/connections/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /connections/search-connection-people
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
viewMoreActivitiesByInterest:
|
viewMoreActivitiesByInterest:
|
||||||
@@ -300,7 +315,7 @@ viewMoreActivitiesByInterest:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/view-more-activities
|
path: /activities/view-more-activities
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
viewMoreActivitiesUpperSection:
|
viewMoreActivitiesUpperSection:
|
||||||
@@ -315,7 +330,7 @@ viewMoreActivitiesUpperSection:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/view-more-activities-upper-section
|
path: /activities/view-more-activities-upper-section
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getRandomActiveActivity:
|
getRandomActiveActivity:
|
||||||
@@ -330,7 +345,7 @@ getRandomActiveActivity:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/get-random-active-activity
|
path: /activities/get-random-active-activity
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
getNearbyActivities:
|
getNearbyActivities:
|
||||||
@@ -345,5 +360,125 @@ getNearbyActivities:
|
|||||||
- ${file(./serverless/patterns/base.yml):pattern4}
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
events:
|
events:
|
||||||
- httpApi:
|
- httpApi:
|
||||||
path: /user/activities/get-nearby-activities
|
path: /activities/get-nearby-activities
|
||||||
method: get
|
method: get
|
||||||
|
|
||||||
|
addActivityToBucketInterested:
|
||||||
|
handler: src/modules/user/handlers/activities/addToBucketInterested.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/handlers/activities/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /activities/add-to-bucket-interested
|
||||||
|
method: post
|
||||||
|
|
||||||
|
removeActivityFromBucketInterested:
|
||||||
|
handler: src/modules/user/handlers/activities/removeFromBucketInterested.handler
|
||||||
|
memorySize: 384
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/handlers/activities/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /activities/remove-from-bucket-interested
|
||||||
|
method: post
|
||||||
|
|
||||||
|
getFilteredLandingPageAllDetails:
|
||||||
|
handler: src/modules/user/handlers/activities/filteredLandingPageAllDetails.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /activities/get-filtered-landing-page-details
|
||||||
|
method: get
|
||||||
|
|
||||||
|
getAllBucketActivities:
|
||||||
|
handler: src/modules/user/handlers/activities/getAllBucketActivities.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /activities/get-all-bucket-activities
|
||||||
|
method: get
|
||||||
|
|
||||||
|
getUserItineraryDetails:
|
||||||
|
handler: src/modules/user/handlers/itinerary/getUserItineraryDetails.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /itinerary/get-user-itinerary-details
|
||||||
|
method: get
|
||||||
|
|
||||||
|
saveUserItinerary:
|
||||||
|
handler: src/modules/user/handlers/itinerary/saveUserItinerary.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /itinerary/save-user-itinerary
|
||||||
|
method: post
|
||||||
|
|
||||||
|
getAllUserSavedItineraries:
|
||||||
|
handler: src/modules/user/handlers/itinerary/getAllUserSavedItineraries.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /itinerary/get-all-user-saved-itineraries
|
||||||
|
method: get
|
||||||
|
|
||||||
|
getMatchingBucketInterestedActivities:
|
||||||
|
handler: src/modules/user/handlers/itinerary/getMatchingBucketInterestedActivities.handler
|
||||||
|
memorySize: 512
|
||||||
|
package:
|
||||||
|
patterns:
|
||||||
|
- 'src/modules/user/**'
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern1}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern2}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern3}
|
||||||
|
- ${file(./serverless/patterns/base.yml):pattern4}
|
||||||
|
events:
|
||||||
|
- httpApi:
|
||||||
|
path: /itinerary/get-matching-bucket-interested-activities
|
||||||
|
method: post
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const ACTIVITY_DISPLAY_STATUS = {
|
|||||||
PQ_IN_REVIEW: 'PQ In Review',
|
PQ_IN_REVIEW: 'PQ In Review',
|
||||||
PQ_APPROVED: 'PQ Approved',
|
PQ_APPROVED: 'PQ Approved',
|
||||||
|
|
||||||
ACTIVITY_DRAFT: 'Draft - Activity',
|
ACTIVITY_DRAFT: 'Draft',
|
||||||
ACTIVITY_IN_REVIEW: 'In Review',
|
ACTIVITY_IN_REVIEW: 'In Review',
|
||||||
ACTIVITY_TO_REVIEW: 'Re-submitted',
|
ACTIVITY_TO_REVIEW: 'Re-submitted',
|
||||||
NOT_LISTED: 'Not Listed',
|
NOT_LISTED: 'Not Listed',
|
||||||
@@ -94,7 +94,7 @@ export const ACTIVITY_AM_DISPLAY_STATUS = {
|
|||||||
PQ_APPROVED: 'PQ Approved',
|
PQ_APPROVED: 'PQ Approved',
|
||||||
REVISED: 'Revised',
|
REVISED: 'Revised',
|
||||||
|
|
||||||
ACTIVITY_DRAFT: 'Draft - Activity',
|
ACTIVITY_DRAFT: 'Draft',
|
||||||
ACTIVITY_NEW: 'New',
|
ACTIVITY_NEW: 'New',
|
||||||
ACTIVITY_TO_REVIEW: 'Activity To Review',
|
ACTIVITY_TO_REVIEW: 'Activity To Review',
|
||||||
ACTIVITY_ENHANCING: 'Enhancing',
|
ACTIVITY_ENHANCING: 'Enhancing',
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const EquipmentDto = z.object({
|
|||||||
|
|
||||||
/* ================= NAVIGATION MODE ================= */
|
/* ================= NAVIGATION MODE ================= */
|
||||||
export const NavigationModeDto = z.object({
|
export const NavigationModeDto = z.object({
|
||||||
navigationModeXid: z.number().int(),
|
navigationModeName: z.string().optional(),
|
||||||
isChargeable: z.boolean().optional(),
|
isChargeable: z.boolean().optional(),
|
||||||
totalPrice: z.number().int().optional().default(0),
|
totalPrice: z.number().int().optional().default(0),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { verifyHostToken } from '../../../../../common/middlewares/jwt/authForHo
|
|||||||
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
|
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
|
||||||
import ApiError from '../../../../../common/utils/helper/ApiError';
|
import ApiError from '../../../../../common/utils/helper/ApiError';
|
||||||
import { HostService } from '../../../services/host.service';
|
import { HostService } from '../../../services/host.service';
|
||||||
|
import { sendPQPEmailToAM } from '../../../services/sendHostResubmitEmailToAM.service';
|
||||||
|
|
||||||
const hostService = new HostService(prismaClient);
|
const hostService = new HostService(prismaClient);
|
||||||
|
|
||||||
@@ -177,6 +178,15 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
|
|
||||||
const getAllUpdatedQuestionResponse = await hostService.getAllPQUpdatedResponse(activityXid)
|
const getAllUpdatedQuestionResponse = await hostService.getAllPQUpdatedResponse(activityXid)
|
||||||
|
|
||||||
|
const details = await hostService.getSuggestionDetails(user.id);
|
||||||
|
|
||||||
|
await sendPQPEmailToAM(
|
||||||
|
details.hostDetails.accountManager.emailAddress,
|
||||||
|
details.hostDetails.accountManager.firstName,
|
||||||
|
details.hostDetails.companyName,
|
||||||
|
details.hostDetails.user.userRefNumber,
|
||||||
|
)
|
||||||
|
|
||||||
// CASE 2 — NO deletion & NO new files => DO NOTHING to existing files
|
// CASE 2 — NO deletion & NO new files => DO NOTHING to existing files
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -13,6 +13,40 @@ const hostService = new HostService(prismaClient);
|
|||||||
|
|
||||||
const s3 = new AWS.S3({ region: config.aws.region });
|
const s3 = new AWS.S3({ region: config.aws.region });
|
||||||
|
|
||||||
|
function parseMultipartFieldValue(val: string) {
|
||||||
|
if (val === '' || val === 'null' || val === 'undefined') return null;
|
||||||
|
|
||||||
|
const cleaned = val.trim();
|
||||||
|
const looksLikeJson =
|
||||||
|
(cleaned.startsWith('{') && cleaned.endsWith('}')) ||
|
||||||
|
(cleaned.startsWith('[') && cleaned.endsWith(']')) ||
|
||||||
|
(cleaned.startsWith('"') && cleaned.endsWith('"'));
|
||||||
|
|
||||||
|
if (!looksLikeJson) return val;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(cleaned);
|
||||||
|
} catch {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeComments(comments: unknown): string | null {
|
||||||
|
if (comments === null || comments === undefined || comments === '') return null;
|
||||||
|
|
||||||
|
const value = String(comments).trim();
|
||||||
|
if (!value) return null;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(value.startsWith('"') && value.endsWith('"')) ||
|
||||||
|
(value.startsWith("'") && value.endsWith("'"))
|
||||||
|
) {
|
||||||
|
return value.slice(1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
// Function to extract S3 key from URL
|
// Function to extract S3 key from URL
|
||||||
function getS3KeyFromUrl(url: string): string {
|
function getS3KeyFromUrl(url: string): string {
|
||||||
const bucketBaseUrl = `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/`;
|
const bucketBaseUrl = `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/`;
|
||||||
@@ -122,22 +156,7 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
|
|
||||||
bb.on("field", (fieldname, val) => {
|
bb.on("field", (fieldname, val) => {
|
||||||
console.log(`FIELD RAW: ${fieldname} =`, val);
|
console.log(`FIELD RAW: ${fieldname} =`, val);
|
||||||
if (val === '' || val === 'null' || val === 'undefined') fields[fieldname] = null;
|
fields[fieldname] = parseMultipartFieldValue(val);
|
||||||
else {
|
|
||||||
try {
|
|
||||||
const cleaned = val.trim();
|
|
||||||
|
|
||||||
// If it starts and ends with quotes, remove them
|
|
||||||
const withoutQuotes =
|
|
||||||
(cleaned.startsWith('"') && cleaned.endsWith('"'))
|
|
||||||
? cleaned.slice(1, -1)
|
|
||||||
: cleaned;
|
|
||||||
|
|
||||||
fields[fieldname] = JSON.parse(withoutQuotes);
|
|
||||||
} catch {
|
|
||||||
fields[fieldname] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
bb.on("close", () => resolve());
|
bb.on("close", () => resolve());
|
||||||
@@ -154,7 +173,7 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
const activityXid = Number(fields.activityXid);
|
const activityXid = Number(fields.activityXid);
|
||||||
const pqqQuestionXid = Number(fields.pqqQuestionXid);
|
const pqqQuestionXid = Number(fields.pqqQuestionXid);
|
||||||
const pqqAnswerXid = Number(fields.pqqAnswerXid);
|
const pqqAnswerXid = Number(fields.pqqAnswerXid);
|
||||||
const comments = fields.comments || null;
|
const comments = normalizeComments(fields.comments);
|
||||||
|
|
||||||
if (!activityXid || isNaN(activityXid)) throw new ApiError(400, "Please provide a valid activity");
|
if (!activityXid || isNaN(activityXid)) throw new ApiError(400, "Please provide a valid activity");
|
||||||
if (!pqqQuestionXid || isNaN(pqqQuestionXid)) throw new ApiError(400, "Please select a valid question");
|
if (!pqqQuestionXid || isNaN(pqqQuestionXid)) throw new ApiError(400, "Please select a valid question");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { verifyHostToken } from '../../../../../common/middlewares/jwt/authForHost';
|
|
||||||
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
import { prismaClient } from '../../../../../common/database/prisma.lambda.service';
|
import { prismaClient } from '../../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyHostToken } from '../../../../../common/middlewares/jwt/authForHost';
|
||||||
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
|
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
|
||||||
import ApiError from '../../../../../common/utils/helper/ApiError';
|
import ApiError from '../../../../../common/utils/helper/ApiError';
|
||||||
import { HostService } from '../../../services/host.service';
|
import { HostService } from '../../../services/host.service';
|
||||||
@@ -25,9 +25,8 @@ export const handler = safeHandler(async (
|
|||||||
// Verify token and get user info
|
// Verify token and get user info
|
||||||
const userInfo = await verifyHostToken(token);
|
const userInfo = await verifyHostToken(token);
|
||||||
|
|
||||||
|
// Accept agreement and get dynamic fields and PDF URL
|
||||||
// Add suggestion using service
|
const result = await hostService.acceptMinglarAgreement(userInfo.id);
|
||||||
await hostService.acceptMinglarAgreement(userInfo.id);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
@@ -38,7 +37,10 @@ export const handler = safeHandler(async (
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Application accepted successfully',
|
message: 'Application accepted successfully',
|
||||||
data: null,
|
data: {
|
||||||
|
filePath: result.filePath,
|
||||||
|
dynamicFields: result.dynamicFields,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { verifyMinglarAdminHostToken } from '../../../../../common/middlewares/jwt/authForMinglarAdminHost';
|
||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../../common/database/prisma.lambda.service';
|
||||||
|
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../../common/utils/helper/ApiError';
|
||||||
|
import { HostService } from '../../../services/host.service';
|
||||||
|
|
||||||
|
const hostService = new HostService(prismaClient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get latest active agreement for a specific host by hostXid.
|
||||||
|
* Accessible for Minglar Admin / Host Admin using admin-host token.
|
||||||
|
*/
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate admin/host admin token
|
||||||
|
await verifyMinglarAdminHostToken(token);
|
||||||
|
|
||||||
|
const hostXidParam =
|
||||||
|
event.queryStringParameters?.hostXid ?? event.queryStringParameters?.host_xid;
|
||||||
|
|
||||||
|
const hostXid = Number(hostXidParam);
|
||||||
|
|
||||||
|
if (!hostXidParam) {
|
||||||
|
throw new ApiError(400, 'hostXid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Number.isNaN(hostXid)) {
|
||||||
|
throw new ApiError(400, 'Invalid hostXid format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const agreement = await hostService.getLatestHostAgreement(hostXid);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Latest host agreement retrieved successfully',
|
||||||
|
data: agreement,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -142,6 +142,10 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
|
|
||||||
const deletedFiles = normalizeJsonField(fields, "deletedFiles") || [];
|
const deletedFiles = normalizeJsonField(fields, "deletedFiles") || [];
|
||||||
const parentDeletedFiles = normalizeJsonField(fields, "parentDeletedFiles") || [];
|
const parentDeletedFiles = normalizeJsonField(fields, "parentDeletedFiles") || [];
|
||||||
|
const deleteCompanyLogo =
|
||||||
|
fields.deleteCompanyLogo === 'true' || fields.deleteCompanyLogo === true;
|
||||||
|
const deleteParentCompanyLogo =
|
||||||
|
fields.deleteParentCompanyLogo === 'true' || fields.deleteParentCompanyLogo === true;
|
||||||
|
|
||||||
/** 4) Extract and clean isDraft flag */
|
/** 4) Extract and clean isDraft flag */
|
||||||
const isDraft = fields.isDraft === 'true' || fields.isDraft === true;
|
const isDraft = fields.isDraft === 'true' || fields.isDraft === true;
|
||||||
@@ -379,6 +383,63 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DELETE EXISTING LOGO IF REQUESTED */
|
||||||
|
if (deleteCompanyLogo) {
|
||||||
|
const existingHost = await prismaClient.hostHeader.findFirst({
|
||||||
|
where: { userXid: userInfo.id },
|
||||||
|
select: { logoPath: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingHost?.logoPath) {
|
||||||
|
try {
|
||||||
|
const s3Key = getS3KeyFromUrl(existingHost.logoPath);
|
||||||
|
await deleteFromS3(s3Key);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('S3 delete failed for company logo:', existingHost.logoPath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedCompany.logoPath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** DELETE EXISTING PARENT COMPANY LOGO IF REQUESTED */
|
||||||
|
if (deleteParentCompanyLogo && parsedCompany.isSubsidairy) {
|
||||||
|
const existingHost = await prismaClient.hostHeader.findFirst({
|
||||||
|
where: { userXid: userInfo.id },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
hostParent: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
logoPath: true,
|
||||||
|
},
|
||||||
|
take: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const existingParent = Array.isArray(existingHost?.hostParent)
|
||||||
|
? existingHost.hostParent[0]
|
||||||
|
: existingHost?.hostParent;
|
||||||
|
|
||||||
|
if (existingParent?.logoPath) {
|
||||||
|
try {
|
||||||
|
const s3Key = getS3KeyFromUrl(existingParent.logoPath);
|
||||||
|
await deleteFromS3(s3Key);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('S3 delete failed for parent company logo:', existingParent.logoPath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedParentCompany) {
|
||||||
|
parsedParentCompany.logoPath = null;
|
||||||
|
} else {
|
||||||
|
parsedParentCompany = {
|
||||||
|
logoPath: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** UPLOAD LOGO (if provided) */
|
/** UPLOAD LOGO (if provided) */
|
||||||
const logoFile = files.find(
|
const logoFile = files.find(
|
||||||
(f) => f.fieldName === 'companyLogo' || f.fieldName === 'companyLogoFile'
|
(f) => f.fieldName === 'companyLogo' || f.fieldName === 'companyLogoFile'
|
||||||
@@ -449,6 +510,7 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise<
|
|||||||
parsedParentCompany,
|
parsedParentCompany,
|
||||||
uploadedParentDocs,
|
uploadedParentDocs,
|
||||||
isDraft,
|
isDraft,
|
||||||
|
{ deleteCompanyLogo, deleteParentCompanyLogo },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!createdOrUpdated) throw new ApiError(400, 'Failed to add/update company details.');
|
if (!createdOrUpdated) throw new ApiError(400, 'Failed to add/update company details.');
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const handler = safeHandler(async (
|
|||||||
data: {
|
data: {
|
||||||
stepper: host?.host?.stepper || null,
|
stepper: host?.host?.stepper || null,
|
||||||
emailAddress: host.user?.emailAddress || null,
|
emailAddress: host.user?.emailAddress || null,
|
||||||
|
hostId: host.user?.userRefNumber || null,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|||||||
344
src/modules/host/handlers/updateHostProfile.ts
Normal file
344
src/modules/host/handlers/updateHostProfile.ts
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import AWS from 'aws-sdk';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { prismaClient } from '../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyHostToken } from '../../../common/middlewares/jwt/authForHost';
|
||||||
|
import { ROLE } from '../../../common/utils/constants/common.constant';
|
||||||
|
import { safeHandler } from '../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from "../../../common/utils/helper/ApiError";
|
||||||
|
import { parseMultipartFormData } from '../../../common/utils/helper/parseMultipartFormData';
|
||||||
|
import config from '../../../config/config';
|
||||||
|
|
||||||
|
const s3 = new AWS.S3({
|
||||||
|
region: config.aws.region,
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateHostProfileSchema = z
|
||||||
|
.strictObject({
|
||||||
|
// Personal
|
||||||
|
fullName: z.string().min(1).optional(),
|
||||||
|
firstName: z.string().min(1).optional(),
|
||||||
|
lastName: z.string().min(1).optional(),
|
||||||
|
isdCode: z.string().min(1).max(6).optional(),
|
||||||
|
mobileNumber: z.string().min(5).max(15).optional(),
|
||||||
|
dateOfBirth: z.string().min(1).optional(),
|
||||||
|
|
||||||
|
profileImage: z.string().url().optional(),
|
||||||
|
|
||||||
|
// Address
|
||||||
|
address1: z.string().min(1).optional(),
|
||||||
|
address2: z.string().min(1).optional(),
|
||||||
|
countryXid: z.number().int().positive().optional(),
|
||||||
|
stateXid: z.number().int().positive().optional(),
|
||||||
|
cityXid: z.number().int().positive().optional(),
|
||||||
|
pinCode: z.string().min(1).optional(),
|
||||||
|
|
||||||
|
// explicitly forbidden
|
||||||
|
emailAddress: z.any().optional(),
|
||||||
|
})
|
||||||
|
.strip();
|
||||||
|
|
||||||
|
async function uploadProfileImageToS3(buffer: Buffer, mimeType: string, originalName: string, userId: number) {
|
||||||
|
const sanitizeFileName = (name: string) => {
|
||||||
|
return name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9.]/g, '_')
|
||||||
|
.replace(/_+/g, '_')
|
||||||
|
.replace(/^_+|_+$/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileExtension = originalName.split('.').pop() || 'jpg';
|
||||||
|
const fileName = `profile_image.${fileExtension}`;
|
||||||
|
const sanitizedFileName = sanitizeFileName(fileName);
|
||||||
|
const s3Key = `Host/ProfileImages/${userId}/${sanitizedFileName}`;
|
||||||
|
|
||||||
|
await s3
|
||||||
|
.upload({
|
||||||
|
Bucket: config.aws.bucketName,
|
||||||
|
Key: s3Key,
|
||||||
|
Body: buffer,
|
||||||
|
ContentType: mimeType,
|
||||||
|
ACL: 'private',
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
|
||||||
|
return `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/${s3Key}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDob(dateOfBirth: string): Date {
|
||||||
|
const parsed = dayjs(dateOfBirth, ['YYYY-MM-DD', 'MM/DD/YYYY', 'DD/MM/YYYY'], true);
|
||||||
|
if (!parsed.isValid()) {
|
||||||
|
throw new ApiError(400, 'Invalid dateOfBirth. Use YYYY-MM-DD (recommended) or MM/DD/YYYY.');
|
||||||
|
}
|
||||||
|
return parsed.toDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitFullName(fullName: string): { firstName: string; lastName: string | null } {
|
||||||
|
const parts = fullName.trim().split(/\s+/).filter(Boolean);
|
||||||
|
const firstName = parts[0] || '';
|
||||||
|
const lastName = parts.length > 1 ? parts.slice(1).join(' ') : null;
|
||||||
|
return { firstName, lastName };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAuthToken(event: APIGatewayProxyEvent): string {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJsonBody(event: APIGatewayProxyEvent): any {
|
||||||
|
try {
|
||||||
|
return event.body ? JSON.parse(event.body) : {};
|
||||||
|
} catch {
|
||||||
|
throw new ApiError(400, 'Invalid JSON in request body');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateBody(body: any) {
|
||||||
|
const parsed = updateHostProfileSchema.safeParse(body);
|
||||||
|
if (!parsed.success) {
|
||||||
|
throw new ApiError(400, parsed.error.issues.map((i) => i.message).join(', '));
|
||||||
|
}
|
||||||
|
if (parsed.data.emailAddress !== undefined) {
|
||||||
|
throw new ApiError(400, 'Email address cannot be updated.');
|
||||||
|
}
|
||||||
|
return parsed.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeNameFields(data: any): { firstName?: string; lastName?: string | null } {
|
||||||
|
if (data.fullName && !data.firstName && !data.lastName) {
|
||||||
|
const split = splitFullName(data.fullName);
|
||||||
|
return { firstName: split.firstName, lastName: split.lastName };
|
||||||
|
}
|
||||||
|
return { firstName: data.firstName, lastName: data.lastName };
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildAddressInput(data: any) {
|
||||||
|
return {
|
||||||
|
address1: data.address1,
|
||||||
|
address2: data.address2,
|
||||||
|
countryXid: data.countryXid,
|
||||||
|
stateXid: data.stateXid,
|
||||||
|
cityXid: data.cityXid,
|
||||||
|
pinCode: data.pinCode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasAnyDefined(obj: Record<string, unknown>) {
|
||||||
|
return Object.values(obj).some((v) => v !== undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureHostUser(tx: any, userId: number) {
|
||||||
|
const user = await tx.user.findUnique({
|
||||||
|
where: { id: userId, isActive: true },
|
||||||
|
select: { id: true, roleXid: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) throw new ApiError(404, 'User not found');
|
||||||
|
if (user.roleXid !== ROLE.HOST) throw new ApiError(403, 'Access denied.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateUserIfNeeded(
|
||||||
|
tx: any,
|
||||||
|
userId: number,
|
||||||
|
input: {
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string | null;
|
||||||
|
isdCode?: string;
|
||||||
|
mobileNumber?: string;
|
||||||
|
dateOfBirth?: string;
|
||||||
|
profileImage?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const userUpdateData: any = {};
|
||||||
|
if (input.firstName !== undefined) userUpdateData.firstName = input.firstName || null;
|
||||||
|
if (input.lastName !== undefined) userUpdateData.lastName = input.lastName;
|
||||||
|
if (input.isdCode !== undefined) userUpdateData.isdCode = input.isdCode || null;
|
||||||
|
if (input.mobileNumber !== undefined) userUpdateData.mobileNumber = input.mobileNumber || null;
|
||||||
|
if (input.dateOfBirth !== undefined) {
|
||||||
|
userUpdateData.dateOfBirth = input.dateOfBirth ? parseDob(input.dateOfBirth) : null;
|
||||||
|
}
|
||||||
|
if (input.profileImage !== undefined) {
|
||||||
|
userUpdateData.profileImage = input.profileImage || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAnyDefined(userUpdateData)) return;
|
||||||
|
|
||||||
|
await tx.user.update({
|
||||||
|
where: { id: userId },
|
||||||
|
data: {
|
||||||
|
...userUpdateData,
|
||||||
|
isProfileUpdated: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function upsertAddressIfNeeded(tx: any, userId: number, addressData: Record<string, any>) {
|
||||||
|
if (!hasAnyDefined(addressData)) return;
|
||||||
|
|
||||||
|
const existingAddress = await tx.userAddressDetails.findFirst({
|
||||||
|
where: { userXid: userId, isActive: true },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const addressUpdateData: any = {};
|
||||||
|
if (addressData.address1 !== undefined) addressUpdateData.address1 = addressData.address1;
|
||||||
|
if (addressData.address2 !== undefined) addressUpdateData.address2 = addressData.address2;
|
||||||
|
if (addressData.countryXid !== undefined) addressUpdateData.countryXid = addressData.countryXid;
|
||||||
|
if (addressData.stateXid !== undefined) addressUpdateData.stateXid = addressData.stateXid;
|
||||||
|
if (addressData.cityXid !== undefined) addressUpdateData.cityXid = addressData.cityXid;
|
||||||
|
if (addressData.pinCode !== undefined) addressUpdateData.pinCode = addressData.pinCode;
|
||||||
|
|
||||||
|
if (existingAddress) {
|
||||||
|
await tx.userAddressDetails.update({
|
||||||
|
where: { id: existingAddress.id },
|
||||||
|
data: addressUpdateData,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const required = ['address1', 'countryXid', 'stateXid', 'cityXid', 'pinCode'] as const;
|
||||||
|
const missing = required.filter((k) => addressData[k] === undefined);
|
||||||
|
if (missing.length) {
|
||||||
|
throw new ApiError(400, `Missing required address fields: ${missing.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tx.userAddressDetails.create({
|
||||||
|
data: {
|
||||||
|
userXid: userId,
|
||||||
|
...addressUpdateData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getProfileSnapshot(tx: any, userId: number) {
|
||||||
|
const updated = await tx.user.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
emailAddress: true,
|
||||||
|
isdCode: true,
|
||||||
|
mobileNumber: true,
|
||||||
|
dateOfBirth: true,
|
||||||
|
profileImage: true,
|
||||||
|
isProfileUpdated: true,
|
||||||
|
userAddressDetails: {
|
||||||
|
where: { isActive: true },
|
||||||
|
take: 1,
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
address1: true,
|
||||||
|
address2: true,
|
||||||
|
countryXid: true,
|
||||||
|
stateXid: true,
|
||||||
|
cityXid: true,
|
||||||
|
pinCode: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: updated,
|
||||||
|
address: updated?.userAddressDetails?.[0] ?? null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = getAuthToken(event);
|
||||||
|
const userInfo = await verifyHostToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
if (!userId || Number.isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user id');
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = event.headers['Content-Type'] || event.headers['content-type'] || '';
|
||||||
|
const isMultipart = contentType.includes('multipart/form-data');
|
||||||
|
|
||||||
|
let body: any;
|
||||||
|
|
||||||
|
if (isMultipart) {
|
||||||
|
const isBase64Encoded = event.isBase64Encoded || false;
|
||||||
|
const { fields, files } = parseMultipartFormData(event.body || null, contentType, isBase64Encoded);
|
||||||
|
|
||||||
|
const multipartBody: any = {};
|
||||||
|
|
||||||
|
const copyIfPresent = (key: string) => {
|
||||||
|
if (fields[key] !== undefined) {
|
||||||
|
multipartBody[key] = fields[key];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
['fullName', 'firstName', 'lastName', 'isdCode', 'mobileNumber', 'dateOfBirth', 'address1', 'address2', 'pinCode'].forEach(
|
||||||
|
copyIfPresent,
|
||||||
|
);
|
||||||
|
|
||||||
|
const parseNumberField = (key: string) => {
|
||||||
|
if (fields[key] !== undefined) {
|
||||||
|
const value = Number(fields[key]);
|
||||||
|
if (!Number.isNaN(value)) {
|
||||||
|
multipartBody[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
['countryXid', 'stateXid', 'cityXid'].forEach(parseNumberField);
|
||||||
|
|
||||||
|
const profileImageFile = files.find((f) => f.fieldName === 'profileImage');
|
||||||
|
if (profileImageFile) {
|
||||||
|
const uploadedUrl = await uploadProfileImageToS3(
|
||||||
|
profileImageFile.data,
|
||||||
|
profileImageFile.contentType,
|
||||||
|
profileImageFile.fileName,
|
||||||
|
userId,
|
||||||
|
);
|
||||||
|
multipartBody.profileImage = uploadedUrl;
|
||||||
|
} else if (fields.profileImage) {
|
||||||
|
multipartBody.profileImage = fields.profileImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
body = multipartBody;
|
||||||
|
} else {
|
||||||
|
body = parseJsonBody(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = validateBody(body);
|
||||||
|
const name = normalizeNameFields(data);
|
||||||
|
const address = buildAddressInput(data);
|
||||||
|
|
||||||
|
const result = await prismaClient.$transaction(async (tx) => {
|
||||||
|
await ensureHostUser(tx, userId);
|
||||||
|
await updateUserIfNeeded(tx, userId, {
|
||||||
|
firstName: name.firstName,
|
||||||
|
lastName: name.lastName,
|
||||||
|
isdCode: data.isdCode,
|
||||||
|
mobileNumber: data.mobileNumber,
|
||||||
|
dateOfBirth: data.dateOfBirth,
|
||||||
|
profileImage: data.profileImage,
|
||||||
|
});
|
||||||
|
await upsertAddressIfNeeded(tx, userId, address);
|
||||||
|
return getProfileSnapshot(tx, userId);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Profile updated successfully',
|
||||||
|
data : null// no data payload per request
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -362,6 +362,9 @@ export class SchedulingService {
|
|||||||
isActive: true,
|
isActive: true,
|
||||||
startDate: { lte: date },
|
startDate: { lte: date },
|
||||||
OR: [{ endDate: null }, { endDate: { gte: date } }],
|
OR: [{ endDate: null }, { endDate: { gte: date } }],
|
||||||
|
ScheduleDetails: {
|
||||||
|
some: {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
activityVenue: {
|
activityVenue: {
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ function computeBasePriceAndTaxes(
|
|||||||
return { basePrice, taxDetails };
|
return { basePrice, taxDetails };
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalize = (v?: string | null) =>
|
const normalize = (v?: string | null, maxLength: number = 50) =>
|
||||||
v ? v.trim().toLowerCase() : null;
|
v ? v.trim().toLowerCase().substring(0, maxLength) : null;
|
||||||
|
|
||||||
async function renderAgreementPdf(vars: {
|
async function renderAgreementPdf(vars: {
|
||||||
effectiveDate: string;
|
effectiveDate: string;
|
||||||
@@ -338,9 +338,11 @@ const findOrCreateState = async (
|
|||||||
) => {
|
) => {
|
||||||
if (!stateName || !countryXid) return null;
|
if (!stateName || !countryXid) return null;
|
||||||
|
|
||||||
|
const trimmedStateName = stateName.trim().substring(0, 50);
|
||||||
|
|
||||||
const state = await tx.states.findFirst({
|
const state = await tx.states.findFirst({
|
||||||
where: {
|
where: {
|
||||||
stateName: { equals: stateName.trim(), mode: 'insensitive' },
|
stateName: { equals: trimmedStateName, mode: 'insensitive' },
|
||||||
countryXid,
|
countryXid,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
@@ -350,7 +352,7 @@ const findOrCreateState = async (
|
|||||||
|
|
||||||
const created = await tx.states.create({
|
const created = await tx.states.create({
|
||||||
data: {
|
data: {
|
||||||
stateName: stateName.trim(),
|
stateName: trimmedStateName,
|
||||||
countryXid,
|
countryXid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -365,9 +367,11 @@ const findOrCreateCity = async (
|
|||||||
) => {
|
) => {
|
||||||
if (!cityName || !stateXid) return null;
|
if (!cityName || !stateXid) return null;
|
||||||
|
|
||||||
|
const trimmedCityName = cityName.trim().substring(0, 50);
|
||||||
|
|
||||||
const city = await tx.cities.findFirst({
|
const city = await tx.cities.findFirst({
|
||||||
where: {
|
where: {
|
||||||
cityName: { equals: cityName.trim(), mode: 'insensitive' },
|
cityName: { equals: trimmedCityName, mode: 'insensitive' },
|
||||||
stateXid,
|
stateXid,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
},
|
},
|
||||||
@@ -377,7 +381,7 @@ const findOrCreateCity = async (
|
|||||||
|
|
||||||
const created = await tx.cities.create({
|
const created = await tx.cities.create({
|
||||||
data: {
|
data: {
|
||||||
cityName: cityName.trim(),
|
cityName: trimmedCityName,
|
||||||
stateXid,
|
stateXid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -391,6 +395,22 @@ const s3 = new AWS.S3({
|
|||||||
region: config.aws.region,
|
region: config.aws.region,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
type UpdateHostProfileInput = {
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string | null;
|
||||||
|
isdCode?: string;
|
||||||
|
mobileNumber?: string;
|
||||||
|
dateOfBirth?: Date;
|
||||||
|
address?: {
|
||||||
|
address1?: string;
|
||||||
|
address2?: string;
|
||||||
|
countryXid?: number;
|
||||||
|
stateXid?: number;
|
||||||
|
cityXid?: number;
|
||||||
|
pinCode?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HostService {
|
export class HostService {
|
||||||
constructor(private prisma: PrismaClient) { }
|
constructor(private prisma: PrismaClient) { }
|
||||||
@@ -415,8 +435,8 @@ export class HostService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const user = await this.prisma.user.findUnique({
|
const user = await this.prisma.user.findUnique({
|
||||||
where: { id: user_xid },
|
where: { id: user_xid, isActive: true },
|
||||||
select: { id: true, emailAddress: true },
|
select: { id: true, emailAddress: true, userRefNumber: true },
|
||||||
});
|
});
|
||||||
return { host, user };
|
return { host, user };
|
||||||
}
|
}
|
||||||
@@ -426,7 +446,46 @@ export class HostService {
|
|||||||
where: { userXid: id },
|
where: { userXid: id },
|
||||||
include: {
|
include: {
|
||||||
hostParent: {
|
hostParent: {
|
||||||
include: {
|
select: {
|
||||||
|
id: true,
|
||||||
|
logoPath: true,
|
||||||
|
companyName: true,
|
||||||
|
address1: true,
|
||||||
|
address2: true,
|
||||||
|
cities: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
cityName: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
stateName: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
countries: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
countryName: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pinCode: true,
|
||||||
|
registrationNumber: true,
|
||||||
|
panNumber: true,
|
||||||
|
gstNumber: true,
|
||||||
|
formationDate: true,
|
||||||
|
companyTypes: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
companyTypeName: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
websiteUrl: true,
|
||||||
|
instagramUrl: true,
|
||||||
|
facebookUrl: true,
|
||||||
|
linkedinUrl: true,
|
||||||
|
twitterUrl: true,
|
||||||
HostParenetDocuments: {
|
HostParenetDocuments: {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -459,12 +518,46 @@ export class HostService {
|
|||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
emailAddress: true,
|
emailAddress: true,
|
||||||
|
dateOfBirth: true,
|
||||||
firstName: true,
|
firstName: true,
|
||||||
lastName: true,
|
lastName: true,
|
||||||
mobileNumber: true,
|
mobileNumber: true,
|
||||||
profileImage: true,
|
profileImage: true,
|
||||||
userStatus: true,
|
userStatus: true,
|
||||||
userRefNumber: true,
|
userRefNumber: true,
|
||||||
|
userAddressDetails: {
|
||||||
|
where: { isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
address1: true,
|
||||||
|
address2: true,
|
||||||
|
locationAddress: true,
|
||||||
|
locationLat: true,
|
||||||
|
locationLong: true,
|
||||||
|
pinCode: true,
|
||||||
|
cityXid: true,
|
||||||
|
cities: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
cityName: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stateXid: true,
|
||||||
|
states: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
stateName: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
countryXid: true,
|
||||||
|
country: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
countryName: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
companyTypes: {
|
companyTypes: {
|
||||||
@@ -577,6 +670,114 @@ export class HostService {
|
|||||||
return this.prisma.user.delete({ where: { id } });
|
return this.prisma.user.delete({ where: { id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the logged-in Host's personal profile details.
|
||||||
|
* Email is intentionally NOT editable here.
|
||||||
|
*/
|
||||||
|
async updateHostProfileDetails(userId: number, input: UpdateHostProfileInput) {
|
||||||
|
return this.prisma.$transaction(async (tx) => {
|
||||||
|
const user = await tx.user.findUnique({
|
||||||
|
where: { id: userId, isActive: true },
|
||||||
|
select: { id: true, roleXid: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) throw new ApiError(404, 'User not found');
|
||||||
|
if (user.roleXid !== ROLE.HOST) throw new ApiError(403, 'Access denied.');
|
||||||
|
|
||||||
|
// 1) Update `User` (whitelist only)
|
||||||
|
const userUpdateData: any = {};
|
||||||
|
if (input.firstName !== undefined) userUpdateData.firstName = input.firstName || null;
|
||||||
|
if (input.lastName !== undefined) userUpdateData.lastName = input.lastName;
|
||||||
|
if (input.isdCode !== undefined) userUpdateData.isdCode = input.isdCode || null;
|
||||||
|
if (input.mobileNumber !== undefined) userUpdateData.mobileNumber = input.mobileNumber || null;
|
||||||
|
if (input.dateOfBirth !== undefined) userUpdateData.dateOfBirth = input.dateOfBirth;
|
||||||
|
|
||||||
|
if (Object.keys(userUpdateData).length > 0) {
|
||||||
|
await tx.user.update({
|
||||||
|
where: { id: userId },
|
||||||
|
data: {
|
||||||
|
...userUpdateData,
|
||||||
|
isProfileUpdated: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Update/Create `UserAddressDetails` (if any address field sent)
|
||||||
|
const addressData = input.address || {};
|
||||||
|
const hasAnyAddressField = Object.values(addressData).some((v) => v !== undefined);
|
||||||
|
|
||||||
|
if (hasAnyAddressField) {
|
||||||
|
const existingAddress = await tx.userAddressDetails.findFirst({
|
||||||
|
where: { userXid: userId, isActive: true },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const addressUpdateData: any = {};
|
||||||
|
if (addressData.address1 !== undefined) addressUpdateData.address1 = addressData.address1;
|
||||||
|
if (addressData.address2 !== undefined) addressUpdateData.address2 = addressData.address2;
|
||||||
|
if (addressData.countryXid !== undefined) addressUpdateData.countryXid = addressData.countryXid;
|
||||||
|
if (addressData.stateXid !== undefined) addressUpdateData.stateXid = addressData.stateXid;
|
||||||
|
if (addressData.cityXid !== undefined) addressUpdateData.cityXid = addressData.cityXid;
|
||||||
|
if (addressData.pinCode !== undefined) addressUpdateData.pinCode = addressData.pinCode;
|
||||||
|
|
||||||
|
if (existingAddress) {
|
||||||
|
await tx.userAddressDetails.update({
|
||||||
|
where: { id: existingAddress.id },
|
||||||
|
data: addressUpdateData,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const required = ['address1', 'countryXid', 'stateXid', 'cityXid', 'pinCode'] as const;
|
||||||
|
const missing = required.filter((k) => addressData[k] === undefined);
|
||||||
|
|
||||||
|
if (missing.length) {
|
||||||
|
throw new ApiError(400, `Missing required address fields: ${missing.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tx.userAddressDetails.create({
|
||||||
|
data: {
|
||||||
|
userXid: userId,
|
||||||
|
...addressUpdateData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Return updated profile snapshot (including read-only email)
|
||||||
|
const updated = await tx.user.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
emailAddress: true,
|
||||||
|
isdCode: true,
|
||||||
|
mobileNumber: true,
|
||||||
|
dateOfBirth: true,
|
||||||
|
profileImage: true,
|
||||||
|
isProfileUpdated: true,
|
||||||
|
userAddressDetails: {
|
||||||
|
where: { isActive: true },
|
||||||
|
take: 1,
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
address1: true,
|
||||||
|
address2: true,
|
||||||
|
countryXid: true,
|
||||||
|
stateXid: true,
|
||||||
|
cityXid: true,
|
||||||
|
pinCode: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: updated,
|
||||||
|
address: updated?.userAddressDetails?.[0] ?? null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async getHostByEmail(email: string): Promise<User> {
|
async getHostByEmail(email: string): Promise<User> {
|
||||||
return this.prisma.user.findUnique({ where: { emailAddress: email } });
|
return this.prisma.user.findUnique({ where: { emailAddress: email } });
|
||||||
}
|
}
|
||||||
@@ -919,55 +1120,150 @@ export class HostService {
|
|||||||
acceptDate,
|
acceptDate,
|
||||||
};
|
};
|
||||||
|
|
||||||
const pdfBuffer = await renderAgreementPdf(agreementVars);
|
let pdfUrl: string | null = null;
|
||||||
|
|
||||||
const existingCount = await this.prisma.hostAgreement.count({
|
try {
|
||||||
where: { hostXid: host.id, isActive: true },
|
const pdfBuffer = await renderAgreementPdf(agreementVars);
|
||||||
});
|
|
||||||
|
|
||||||
const nextVersionNumber = `AG${existingCount + 1}`;
|
const existingCount = await this.prisma.hostAgreement.count({
|
||||||
const baseKey = `Documents/Host/${host.id}/agreements/${nextVersionNumber}`;
|
|
||||||
|
|
||||||
const pdfKey = `${baseKey}.pdf`;
|
|
||||||
|
|
||||||
await s3
|
|
||||||
.upload({
|
|
||||||
Bucket: config.aws.bucketName,
|
|
||||||
Key: pdfKey,
|
|
||||||
Body: pdfBuffer,
|
|
||||||
ContentType: 'application/pdf',
|
|
||||||
ACL: 'private',
|
|
||||||
})
|
|
||||||
.promise();
|
|
||||||
|
|
||||||
const pdfUrl = `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/${pdfKey}`;
|
|
||||||
|
|
||||||
await this.prisma.$transaction(async (tx) => {
|
|
||||||
// Optional: mark previous agreements inactive
|
|
||||||
await tx.hostAgreement.updateMany({
|
|
||||||
where: { hostXid: host.id, isActive: true },
|
where: { hostXid: host.id, isActive: true },
|
||||||
data: { isActive: false },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await tx.hostAgreement.create({
|
const nextVersionNumber = `AG${existingCount + 1}`;
|
||||||
data: {
|
const baseKey = `Documents/Host/${host.id}/agreements/${nextVersionNumber}`;
|
||||||
hostXid: host.id,
|
|
||||||
filePath: pdfUrl,
|
const pdfKey = `${baseKey}.pdf`;
|
||||||
versionNumber: nextVersionNumber,
|
|
||||||
isActive: true,
|
await s3
|
||||||
},
|
.upload({
|
||||||
|
Bucket: config.aws.bucketName,
|
||||||
|
Key: pdfKey,
|
||||||
|
Body: pdfBuffer,
|
||||||
|
ContentType: 'application/pdf',
|
||||||
|
ACL: 'private',
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
|
||||||
|
pdfUrl = `https://${config.aws.bucketName}.s3.${config.aws.region}.amazonaws.com/${pdfKey}`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error generating or uploading PDF:', error);
|
||||||
|
// Continue without PDF - will return dynamic fields instead
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const existingCount = await this.prisma.hostAgreement.count({
|
||||||
|
where: { hostXid: host.id, isActive: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
await tx.hostHeader.update({
|
const nextVersionNumber = `AG${existingCount + 1}`;
|
||||||
where: { id: host.id },
|
|
||||||
data: {
|
await this.prisma.$transaction(async (tx) => {
|
||||||
stepper: STEPPER.AGREEMENT_ACCEPTED,
|
// Optional: mark previous agreements inactive
|
||||||
isApproved: true,
|
await tx.hostAgreement.updateMany({
|
||||||
agreementAccepted: true,
|
where: { hostXid: host.id, isActive: true },
|
||||||
agreementStartDate: host.agreementStartDate || new Date(),
|
data: { isActive: false },
|
||||||
},
|
});
|
||||||
|
|
||||||
|
await tx.hostAgreement.create({
|
||||||
|
data: {
|
||||||
|
hostXid: host.id,
|
||||||
|
filePath: pdfUrl,
|
||||||
|
versionNumber: nextVersionNumber,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await tx.hostHeader.update({
|
||||||
|
where: { id: host.id },
|
||||||
|
data: {
|
||||||
|
stepper: STEPPER.AGREEMENT_ACCEPTED,
|
||||||
|
isApproved: true,
|
||||||
|
agreementAccepted: true,
|
||||||
|
agreementStartDate: host.agreementStartDate || new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating host agreement record:', error);
|
||||||
|
// Continue without creating agreement record - will return dynamic fields instead
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return dynamic fields and PDF URL
|
||||||
|
return {
|
||||||
|
filePath: pdfUrl,
|
||||||
|
dynamicFields: agreementVars,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest (active) agreement for a specific host by hostXid.
|
||||||
|
*/
|
||||||
|
async getLatestHostAgreement(hostXid: number) {
|
||||||
|
if (!hostXid || Number.isNaN(hostXid)) {
|
||||||
|
throw new ApiError(400, 'Valid hostXid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostHeader = await this.prisma.hostHeader.findFirst({
|
||||||
|
where: { id: hostXid, isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
isCommisionBase: true,
|
||||||
|
commisionPer: true,
|
||||||
|
durationNumber: true,
|
||||||
|
durationFrequency: true,
|
||||||
|
amountPerBooking: true,
|
||||||
|
agreementStartDate: true,
|
||||||
|
payoutDurationNum: true,
|
||||||
|
payoutDurationFrequency: true,
|
||||||
|
registrationNumber: true,
|
||||||
|
companyName: true,
|
||||||
|
companyTypes: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
companyTypeName: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const agreement = await this.prisma.hostAgreement.findFirst({
|
||||||
|
where: { hostXid, isActive: true },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
hostXid: true,
|
||||||
|
filePath: true,
|
||||||
|
versionNumber: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ❌ If both missing
|
||||||
|
if (!agreement && !hostHeader) {
|
||||||
|
throw new ApiError(404, 'No active agreement found for this host');
|
||||||
|
}
|
||||||
|
|
||||||
|
let presignedUrl = "";
|
||||||
|
|
||||||
|
if (agreement?.filePath) {
|
||||||
|
const key = agreement.filePath.startsWith('http')
|
||||||
|
? agreement.filePath.split('.com/')[1]
|
||||||
|
: agreement.filePath;
|
||||||
|
|
||||||
|
const bucket = config.aws.bucketName;
|
||||||
|
presignedUrl = await getPresignedUrl(bucket, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hostHeader: hostHeader || null,
|
||||||
|
agreement: agreement
|
||||||
|
? {
|
||||||
|
...agreement,
|
||||||
|
presignedUrl
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPQQQuestionDetail(question_xid: number, activity_xid: number) {
|
async getPQQQuestionDetail(question_xid: number, activity_xid: number) {
|
||||||
@@ -1095,6 +1391,10 @@ export class HostService {
|
|||||||
parentCompanyData?: any | null,
|
parentCompanyData?: any | null,
|
||||||
parentDocuments?: HostDocumentInput[],
|
parentDocuments?: HostDocumentInput[],
|
||||||
isDraft: boolean = false,
|
isDraft: boolean = false,
|
||||||
|
options?: {
|
||||||
|
deleteCompanyLogo?: boolean;
|
||||||
|
deleteParentCompanyLogo?: boolean;
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
return await this.prisma.$transaction(async (tx) => {
|
return await this.prisma.$transaction(async (tx) => {
|
||||||
// Check if host already has a company
|
// Check if host already has a company
|
||||||
@@ -1139,7 +1439,7 @@ export class HostService {
|
|||||||
hostStatusDisplay = HOST_STATUS_DISPLAY.UNDER_REVIEW;
|
hostStatusDisplay = HOST_STATUS_DISPLAY.UNDER_REVIEW;
|
||||||
|
|
||||||
minglarStatusInternal = MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW;
|
minglarStatusInternal = MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW;
|
||||||
minglarStatusDisplay = MINGLAR_STATUS_DISPLAY.TO_REVIEW;
|
minglarStatusDisplay = MINGLAR_STATUS_DISPLAY.RE_SUBMITTED;
|
||||||
}
|
}
|
||||||
// CASE 2: Admin has rejected but host can resubmit
|
// CASE 2: Admin has rejected but host can resubmit
|
||||||
else if (
|
else if (
|
||||||
@@ -1355,7 +1655,9 @@ export class HostService {
|
|||||||
? { connect: { id: Number(companyData.countryXid) } }
|
? { connect: { id: Number(companyData.countryXid) } }
|
||||||
: undefined,
|
: undefined,
|
||||||
pinCode: companyData.pinCode,
|
pinCode: companyData.pinCode,
|
||||||
logoPath: companyData.logoPath || existingHostCompany.logoPath,
|
logoPath: options?.deleteCompanyLogo
|
||||||
|
? companyData.logoPath ?? null
|
||||||
|
: companyData.logoPath || existingHostCompany.logoPath,
|
||||||
isSubsidairy: companyData.isSubsidairy,
|
isSubsidairy: companyData.isSubsidairy,
|
||||||
registrationNumber: companyData.registrationNumber,
|
registrationNumber: companyData.registrationNumber,
|
||||||
panNumber: companyData.panNumber,
|
panNumber: companyData.panNumber,
|
||||||
@@ -1496,10 +1798,11 @@ export class HostService {
|
|||||||
? { connect: { id: Number(parentCompanyData.countryXid) } }
|
? { connect: { id: Number(parentCompanyData.countryXid) } }
|
||||||
: undefined,
|
: undefined,
|
||||||
pinCode: parentCompanyData.pinCode || null,
|
pinCode: parentCompanyData.pinCode || null,
|
||||||
logoPath:
|
logoPath: options?.deleteParentCompanyLogo
|
||||||
parentCompanyData?.logoPath ||
|
? parentCompanyData?.logoPath ?? null
|
||||||
existingParentCompany?.logoPath ||
|
: parentCompanyData?.logoPath ||
|
||||||
null,
|
existingParentCompany?.logoPath ||
|
||||||
|
null,
|
||||||
registrationNumber: parentCompanyData.registrationNumber || null,
|
registrationNumber: parentCompanyData.registrationNumber || null,
|
||||||
panNumber: parentCompanyData.panNumber || null,
|
panNumber: parentCompanyData.panNumber || null,
|
||||||
gstNumber: parentCompanyData.gstNumber || null,
|
gstNumber: parentCompanyData.gstNumber || null,
|
||||||
@@ -1554,10 +1857,11 @@ export class HostService {
|
|||||||
? { connect: { id: Number(parentCompanyData.countryXid) } }
|
? { connect: { id: Number(parentCompanyData.countryXid) } }
|
||||||
: undefined,
|
: undefined,
|
||||||
pinCode: parentCompanyData.pinCode || null,
|
pinCode: parentCompanyData.pinCode || null,
|
||||||
logoPath:
|
logoPath: options?.deleteParentCompanyLogo
|
||||||
parentCompanyData?.logoPath ||
|
? parentCompanyData?.logoPath ?? null
|
||||||
existingParentCompany?.logoPath ||
|
: parentCompanyData?.logoPath ||
|
||||||
null,
|
existingParentCompany?.logoPath ||
|
||||||
|
null,
|
||||||
registrationNumber: parentCompanyData.registrationNumber || null,
|
registrationNumber: parentCompanyData.registrationNumber || null,
|
||||||
panNumber: parentCompanyData.panNumber || null,
|
panNumber: parentCompanyData.panNumber || null,
|
||||||
gstNumber: parentCompanyData.gstNumber || null,
|
gstNumber: parentCompanyData.gstNumber || null,
|
||||||
@@ -2374,15 +2678,9 @@ export class HostService {
|
|||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
|
navigationModeName: true,
|
||||||
isInActivityChargeable: true,
|
isInActivityChargeable: true,
|
||||||
navigationModesTotalPrice: true,
|
navigationModesTotalPrice: true,
|
||||||
navigationMode: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
navigationModeName: true,
|
|
||||||
navigationModeIcon: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
equipmentAvailable: true,
|
equipmentAvailable: true,
|
||||||
@@ -3087,6 +3385,34 @@ export class HostService {
|
|||||||
throw new ApiError(404, 'Activity not found');
|
throw new ApiError(404, 'Activity not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const normalizedActivityTitle =
|
||||||
|
typeof payload.activityTitle === 'string'
|
||||||
|
? payload.activityTitle.trim()
|
||||||
|
: '';
|
||||||
|
|
||||||
|
if (normalizedActivityTitle) {
|
||||||
|
payload.activityTitle = normalizedActivityTitle;
|
||||||
|
|
||||||
|
const duplicateActivity = await tx.activities.findFirst({
|
||||||
|
where: {
|
||||||
|
id: { not: existingActivity.id },
|
||||||
|
isActive: true,
|
||||||
|
activityTitle: {
|
||||||
|
equals: normalizedActivityTitle,
|
||||||
|
mode: 'insensitive',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (duplicateActivity) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'Same activity name already exists. Please choose a different name.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
* 3️⃣ STATUS DECISION
|
* 3️⃣ STATUS DECISION
|
||||||
* -------------------------------- */
|
* -------------------------------- */
|
||||||
@@ -3706,7 +4032,7 @@ export class HostService {
|
|||||||
const navMode = await tx.activityNavigationModes.create({
|
const navMode = await tx.activityNavigationModes.create({
|
||||||
data: {
|
data: {
|
||||||
activityXid,
|
activityXid,
|
||||||
navigationModeXid: mode.navigationModeXid,
|
navigationModeName: mode.navigationModeName,
|
||||||
isInActivityChargeable: isChargeable,
|
isInActivityChargeable: isChargeable,
|
||||||
navigationModesBasePrice: basePrice,
|
navigationModesBasePrice: basePrice,
|
||||||
navigationModesTotalPrice: totalPrice,
|
navigationModesTotalPrice: totalPrice,
|
||||||
|
|||||||
@@ -76,3 +76,41 @@ export async function sendEmailToMinglarAdmin(
|
|||||||
throw new ApiError(500, "Failed to send OTP to host via email.");
|
throw new ApiError(500, "Failed to send OTP to host via email.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function sendPQPEmailToAM(
|
||||||
|
emailAddress: string,
|
||||||
|
minglarAdminName: string,
|
||||||
|
hostCompanyName: string,
|
||||||
|
hostRefNumber: string
|
||||||
|
): Promise<{
|
||||||
|
sent: boolean;
|
||||||
|
// messageId: string
|
||||||
|
}> {
|
||||||
|
|
||||||
|
const subject = `New Pre-qualification Questionnaire from : ${hostCompanyName}`;
|
||||||
|
|
||||||
|
const htmlContent = `
|
||||||
|
<p>Dear ${minglarAdminName},</p>
|
||||||
|
<p>Host ${hostCompanyName} with reference number: <strong>${hostRefNumber}</strong> has submited their pre-qualification questionnaire.</p>
|
||||||
|
<p>Please review their appliaction and take the necessary action.</p>
|
||||||
|
<p>Best regards,<br/>Minglar Team</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await brevoService.sendEmail({
|
||||||
|
recipients: [{ email: emailAddress }],
|
||||||
|
subject,
|
||||||
|
htmlContent,
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log("📧 Email sent successfully:", result);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sent: true,
|
||||||
|
// messageId: result.messageId
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Brevo email send failed:", err);
|
||||||
|
throw new ApiError(500, "Failed to send OTP to host via email.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ export class TokenService {
|
|||||||
config.jwt.secret
|
config.jwt.secret
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.prisma.token.deleteMany({
|
// Optionally keep existing refresh tokens alive instead of deleting
|
||||||
where: { userXid: user_xid }
|
// Removed deleteMany call so the same refresh token can be used multiple
|
||||||
})
|
// times. If you want to limit refresh tokens later you can implement
|
||||||
|
// rotation or blacklist logic elsewhere.
|
||||||
await this.prisma.token.create({
|
await this.prisma.token.create({
|
||||||
data: {
|
data: {
|
||||||
token: refreshToken.token,
|
token: refreshToken.token,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const bucket = config.aws.bucketName;
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MinglarService {
|
export class MinglarService {
|
||||||
constructor(private prisma: PrismaService | PrismaClient) {}
|
constructor(private prisma: PrismaService | PrismaClient) { }
|
||||||
|
|
||||||
async createPassword(user_xid: number, password: string): Promise<boolean> {
|
async createPassword(user_xid: number, password: string): Promise<boolean> {
|
||||||
// Find user by id
|
// Find user by id
|
||||||
@@ -314,6 +314,8 @@ export class MinglarService {
|
|||||||
companyName: true,
|
companyName: true,
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
userRefNumber: true,
|
userRefNumber: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -375,11 +377,52 @@ export class MinglarService {
|
|||||||
const {
|
const {
|
||||||
paginationService,
|
paginationService,
|
||||||
} = require('@/common/utils/pagination/pagination.service');
|
} = require('@/common/utils/pagination/pagination.service');
|
||||||
return paginationService.createPaginatedResponse(
|
|
||||||
|
let hostDetails = null;
|
||||||
|
|
||||||
|
if (hostXid) {
|
||||||
|
hostDetails = await this.prisma.hostHeader.findUnique({
|
||||||
|
where: { id: hostXid },
|
||||||
|
select: {
|
||||||
|
companyName: true,
|
||||||
|
user: {
|
||||||
|
select: {
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
userRefNumber: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const paginatedResponse = paginationService.createPaginatedResponse(
|
||||||
hostActivities,
|
hostActivities,
|
||||||
totalCount,
|
totalCount,
|
||||||
paginationOptions || { page: 1, limit: 10, skip: 0 },
|
paginationOptions || { page: 1, limit: 10, skip: 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 👇 ADD THIS BLOCK
|
||||||
|
if (hostActivities.length === 0 && hostDetails) {
|
||||||
|
paginatedResponse.data = [
|
||||||
|
{
|
||||||
|
id: null,
|
||||||
|
activityRefNumber: null,
|
||||||
|
activityTitle: null,
|
||||||
|
totalScore: null,
|
||||||
|
activityInternalStatus: null,
|
||||||
|
activityDisplayStatus: null,
|
||||||
|
amInternalStatus: null,
|
||||||
|
amDisplayStatus: null,
|
||||||
|
createdAt: null,
|
||||||
|
host: hostDetails,
|
||||||
|
ActivityAmDetails: [],
|
||||||
|
activityType: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return paginatedResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUserRevenue(
|
async createUserRevenue(
|
||||||
@@ -818,7 +861,7 @@ export class MinglarService {
|
|||||||
if (
|
if (
|
||||||
userStatus &&
|
userStatus &&
|
||||||
userStatus.trim().toLowerCase() ===
|
userStatus.trim().toLowerCase() ===
|
||||||
MINGLAR_STATUS_DISPLAY.NEW.toLowerCase()
|
MINGLAR_STATUS_DISPLAY.NEW.toLowerCase()
|
||||||
) {
|
) {
|
||||||
filters.adminStatusInternal = MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW;
|
filters.adminStatusInternal = MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW;
|
||||||
}
|
}
|
||||||
@@ -832,9 +875,9 @@ export class MinglarService {
|
|||||||
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
||||||
display: MINGLAR_STATUS_DISPLAY.NEW,
|
display: MINGLAR_STATUS_DISPLAY.NEW,
|
||||||
},
|
},
|
||||||
To_Review: {
|
Re_Submitted: {
|
||||||
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
||||||
display: MINGLAR_STATUS_DISPLAY.TO_REVIEW,
|
display: MINGLAR_STATUS_DISPLAY.RE_SUBMITTED,
|
||||||
},
|
},
|
||||||
Enhancing: {
|
Enhancing: {
|
||||||
internal: MINGLAR_STATUS_INTERNAL.AM_REJECTED,
|
internal: MINGLAR_STATUS_INTERNAL.AM_REJECTED,
|
||||||
@@ -945,6 +988,7 @@ export class MinglarService {
|
|||||||
const where: any = {
|
const where: any = {
|
||||||
isActive: true,
|
isActive: true,
|
||||||
hostStatusInternal: { notIn: [HOST_STATUS_INTERNAL.DRAFT] },
|
hostStatusInternal: { notIn: [HOST_STATUS_INTERNAL.DRAFT] },
|
||||||
|
adminStatusInternal: { notIn: [MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW] },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (search?.trim()) {
|
if (search?.trim()) {
|
||||||
@@ -1187,15 +1231,15 @@ export class MinglarService {
|
|||||||
// Build search filter if search term is provided
|
// Build search filter if search term is provided
|
||||||
const searchFilter = search
|
const searchFilter = search
|
||||||
? {
|
? {
|
||||||
OR: [
|
OR: [
|
||||||
{ email: { contains: search, mode: 'insensitive' as const } },
|
{ email: { contains: search, mode: 'insensitive' as const } },
|
||||||
{ firstName: { contains: search, mode: 'insensitive' as const } },
|
{ firstName: { contains: search, mode: 'insensitive' as const } },
|
||||||
{ lastName: { contains: search, mode: 'insensitive' as const } },
|
{ lastName: { contains: search, mode: 'insensitive' as const } },
|
||||||
{
|
{
|
||||||
userRefNumber: { contains: search, mode: 'insensitive' as const },
|
userRefNumber: { contains: search, mode: 'insensitive' as const },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
// 1. Fetch all required users (Admin, Co-Admin, AM)
|
// 1. Fetch all required users (Admin, Co-Admin, AM)
|
||||||
@@ -1711,6 +1755,7 @@ export class MinglarService {
|
|||||||
isEmailVerfied: true,
|
isEmailVerfied: true,
|
||||||
isMobileVerfied: true,
|
isMobileVerfied: true,
|
||||||
isBiometric: true,
|
isBiometric: true,
|
||||||
|
createdAt: true,
|
||||||
userAddressDetails: {
|
userAddressDetails: {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -1826,8 +1871,8 @@ export class MinglarService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async rejectActivityApplicationByAM(activityId: number, user_xid: number) {
|
async rejectActivityApplicationByAM(activityId: number, user_xid: number) {
|
||||||
return await this.prisma.$transaction(async (tx) => {
|
return await this.prisma.$transaction(async (tx) => {
|
||||||
await tx.activities.update({
|
await tx.activities.update({
|
||||||
|
|||||||
@@ -27,15 +27,21 @@ export const handler = safeHandler(async (
|
|||||||
// 2) Authenticate user
|
// 2) Authenticate user
|
||||||
await verifyMinglarAdminHostToken(token);
|
await verifyMinglarAdminHostToken(token);
|
||||||
|
|
||||||
// 3) Get bankXid from query params
|
// 3) Get stateXid and optional search term from query params
|
||||||
const stateXid = Number(event.queryStringParameters?.stateXid);
|
const stateXid = Number(event.queryStringParameters?.stateXid);
|
||||||
|
const search = event.queryStringParameters?.search?.trim();
|
||||||
|
|
||||||
if (!stateXid || isNaN(stateXid)) {
|
if (!stateXid || isNaN(stateXid)) {
|
||||||
throw new ApiError(400, "Valid stateXid is required in query params.");
|
throw new ApiError(400, "Valid stateXid is required in query params.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Fetch branches for the bank
|
// If search is provided, enforce minimum 3 characters
|
||||||
const branches = await prePopulateService.getCityByStateId(stateXid);
|
if (search && search.length < 3) {
|
||||||
|
throw new ApiError(400, "Search term must be at least 3 characters long.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Fetch cities for the state (optionally filtered by search)
|
||||||
|
const branches = await prePopulateService.getCityByStateId(stateXid, search);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|||||||
@@ -39,12 +39,20 @@ export class PrePopulateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async getCityByStateId(stateXid: number) {
|
async getCityByStateId(stateXid: number, search?: string) {
|
||||||
return await this.prisma.cities.findMany({
|
return await this.prisma.cities.findMany({
|
||||||
where: {
|
where: {
|
||||||
stateXid,
|
stateXid,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
deletedAt: null
|
deletedAt: null,
|
||||||
|
...(search && search.length >= 3
|
||||||
|
? {
|
||||||
|
cityName: {
|
||||||
|
contains: search,
|
||||||
|
mode: 'insensitive',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
@@ -132,7 +140,9 @@ export class PrePopulateService {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return { documentDetails, countryDetails, stateDetails, companyTypeDetails };
|
const adminEmail = config.MinglarAdminEmail;
|
||||||
|
|
||||||
|
return { documentDetails, countryDetails, stateDetails, companyTypeDetails, adminEmail };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllFrequencies() {
|
async getAllFrequencies() {
|
||||||
@@ -153,7 +163,6 @@ export class PrePopulateService {
|
|||||||
foodType,
|
foodType,
|
||||||
cuisineDetails,
|
cuisineDetails,
|
||||||
vehicleType,
|
vehicleType,
|
||||||
navigationMode,
|
|
||||||
taxDetails,
|
taxDetails,
|
||||||
energyLevel,
|
energyLevel,
|
||||||
aminitiesDetails,
|
aminitiesDetails,
|
||||||
@@ -171,9 +180,6 @@ export class PrePopulateService {
|
|||||||
this.prisma.transportModes.findMany({
|
this.prisma.transportModes.findMany({
|
||||||
where: { isActive: true },
|
where: { isActive: true },
|
||||||
}),
|
}),
|
||||||
this.prisma.navigationModes.findMany({
|
|
||||||
where: { isActive: true },
|
|
||||||
}),
|
|
||||||
this.prisma.taxes.findMany({
|
this.prisma.taxes.findMany({
|
||||||
where: { isActive: true },
|
where: { isActive: true },
|
||||||
}),
|
}),
|
||||||
@@ -215,7 +221,6 @@ export class PrePopulateService {
|
|||||||
foodType,
|
foodType,
|
||||||
cuisineDetails,
|
cuisineDetails,
|
||||||
vehicleType,
|
vehicleType,
|
||||||
navigationMode,
|
|
||||||
taxDetails,
|
taxDetails,
|
||||||
energyLevel,
|
energyLevel,
|
||||||
aminitiesDetails,
|
aminitiesDetails,
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { UserService } from '../../services/user.service';
|
||||||
|
|
||||||
|
const userService = new UserService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
// Extract token from headers
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate user using verifyUserToken
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = userInfo.id;
|
||||||
|
|
||||||
|
if (Number.isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'User id must be a number');
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await userService.getUserById(userId);
|
||||||
|
if (!user) {
|
||||||
|
throw new ApiError(404, 'User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse request body
|
||||||
|
let body: { activityXid: number; isBucket: boolean; bucketTypeName: string; };
|
||||||
|
|
||||||
|
try {
|
||||||
|
body = event.body ? JSON.parse(event.body) : {};
|
||||||
|
} catch (error) {
|
||||||
|
throw new ApiError(400, 'Invalid JSON in request body');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { activityXid, isBucket, bucketTypeName } = body;
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (
|
||||||
|
typeof activityXid !== 'number' ||
|
||||||
|
typeof isBucket !== 'boolean' ||
|
||||||
|
!bucketTypeName
|
||||||
|
) {
|
||||||
|
throw new ApiError(400, 'Required fields missing or invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set the passcode
|
||||||
|
const counts = await userService.addToBucketInterested(userId, isBucket, bucketTypeName, activityXid);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: `Activity added to ${isBucket ? 'bucket' : 'interested'} successfully`,
|
||||||
|
data: {
|
||||||
|
bucketCount: counts.bucketCount,
|
||||||
|
interestedCount: counts.interestedCount,
|
||||||
|
coverImage: counts.coverImage,
|
||||||
|
coverImagePresignedUrl: counts.coverImagePresignedUrl,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -50,64 +50,73 @@ export const handler = safeHandler(async (
|
|||||||
const activity = activityDetails.activity;
|
const activity = activityDetails.activity;
|
||||||
|
|
||||||
// Rooms: combine ActivityVenues with their respective slots for the selected date
|
// Rooms: combine ActivityVenues with their respective slots for the selected date
|
||||||
const Venues = (activity.ActivityVenues || []).map((v: any) => {
|
const Venues = (activity.ActivityVenues || [])
|
||||||
const header = scheduleDetails.find((h: any) => h.activityVenue?.venueXid === v.id);
|
.map((v: any) => {
|
||||||
|
const header = scheduleDetails.find(
|
||||||
|
(h: any) => h.activityVenue?.venueXid === v.id
|
||||||
|
);
|
||||||
|
|
||||||
const roomSlots = (header?.slots || []).map((s: any) => {
|
if (!header || !header.slots?.length) {
|
||||||
let status = 'Available';
|
return null; // ❌ venue has no slots for selected date
|
||||||
if (s.maxCapacity === 0) status = 'Housefull';
|
}
|
||||||
else if (s.maxCapacity <= 2) status = '2 Slots Left';
|
|
||||||
else if (s.maxCapacity <= 5) status = 'Fast Filling';
|
const roomSlots = header.slots.map((s: any) => {
|
||||||
|
let status = "Available";
|
||||||
|
|
||||||
|
if (s.maxCapacity === 0) status = "Housefull";
|
||||||
|
else if (s.maxCapacity <= 2) status = "2 Slots Left";
|
||||||
|
else if (s.maxCapacity <= 5) status = "Fast Filling";
|
||||||
|
|
||||||
|
return {
|
||||||
|
slotId: s.slotId,
|
||||||
|
startTime: s.startTime,
|
||||||
|
endTime: s.endTime,
|
||||||
|
status,
|
||||||
|
maxCapacity: s.maxCapacity,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
slotId: s.slotId,
|
venueXid: v.id,
|
||||||
startTime: s.startTime,
|
venueName: v.venueName,
|
||||||
endTime: s.endTime,
|
venueLabel: v.venueLabel,
|
||||||
status,
|
venueCapacity: v.venueCapacity,
|
||||||
maxCapacity: s.maxCapacity,
|
availableSeats: v.availableSeats ?? null,
|
||||||
|
price: v.ActivityPrices?.[0]?.sellPrice ?? null,
|
||||||
|
endDate: header?.endDate ?? null,
|
||||||
|
slots: roomSlots,
|
||||||
|
slotsCount: roomSlots.length,
|
||||||
|
venueMedia: (v.ActivityVenueArtifacts || []).map((media: any) => ({
|
||||||
|
id: media.id,
|
||||||
|
mediaType: media.mediaType,
|
||||||
|
mediaFileName: media.mediaFileName,
|
||||||
|
presignedUrl: media.presignedUrl,
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
});
|
})
|
||||||
|
.filter(Boolean); // ✅ removes null venues
|
||||||
|
|
||||||
return {
|
// derive check-in/out from all room slots (earliest start, latest end)
|
||||||
venueXid: v.id,
|
const allSlots = Venues.flatMap(r => r.slots || []);
|
||||||
venueName: v.venueName,
|
const startTimes = allSlots.map(s => s.startTime).filter(Boolean);
|
||||||
venueLabel: v.venueLabel,
|
const endTimes = allSlots.map(s => s.endTime).filter(Boolean);
|
||||||
venueCapacity: v.venueCapacity,
|
const checkInTime = startTimes.length ? startTimes.sort()[0] : null;
|
||||||
availableSeats: v.availableSeats ?? null,
|
const checkOutTime = endTimes.length ? endTimes.sort().reverse()[0] : null;
|
||||||
price: v.ActivityPrices?.[0]?.sellPrice ?? null,
|
|
||||||
endDate: header?.endDate ?? null,
|
const responsePayload = {
|
||||||
slots: roomSlots,
|
selectedDate,
|
||||||
slotsCount: roomSlots.length,
|
Venues,
|
||||||
venueMedia: (v.ActivityVenueArtifacts || []).map((media: any) => ({
|
checkInTime,
|
||||||
id: media.id,
|
checkOutTime,
|
||||||
mediaType: media.mediaType,
|
};
|
||||||
mediaFileName: media.mediaFileName, // original S3 key / URL
|
|
||||||
presignedUrl: media.presignedUrl, // presigned URL
|
return {
|
||||||
})),
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ success: true, data: responsePayload }),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// derive check-in/out from all room slots (earliest start, latest end)
|
|
||||||
const allSlots = Venues.flatMap(r => r.slots || []);
|
|
||||||
const startTimes = allSlots.map(s => s.startTime).filter(Boolean);
|
|
||||||
const endTimes = allSlots.map(s => s.endTime).filter(Boolean);
|
|
||||||
const checkInTime = startTimes.length ? startTimes.sort()[0] : null;
|
|
||||||
const checkOutTime = endTimes.length ? endTimes.sort().reverse()[0] : null;
|
|
||||||
|
|
||||||
const responsePayload = {
|
|
||||||
selectedDate,
|
|
||||||
Venues,
|
|
||||||
checkInTime,
|
|
||||||
checkOutTime,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ success: true, data: responsePayload }),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { FilteredLandingPageService } from '../../services/filteredLandingPage.service';
|
||||||
|
|
||||||
|
const filteredLandingPageService = new FilteredLandingPageService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
// Extract token from headers
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify token and get user info
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = Number(event.queryStringParameters?.page ?? 1);
|
||||||
|
const limit = Number(event.queryStringParameters?.limit ?? 20);
|
||||||
|
const countryName = event.queryStringParameters?.countryName ?? '';
|
||||||
|
const stateName = event.queryStringParameters?.stateName ?? '';
|
||||||
|
const cityName = event.queryStringParameters?.cityName ?? '';
|
||||||
|
const userLat = event.queryStringParameters?.userLat ?? '';
|
||||||
|
const userLong = event.queryStringParameters?.userLong ?? '';
|
||||||
|
|
||||||
|
let activityTypeXids: number[] | undefined;
|
||||||
|
if (event.queryStringParameters?.activityTypeXids) {
|
||||||
|
try {
|
||||||
|
activityTypeXids = JSON.parse(event.queryStringParameters.activityTypeXids);
|
||||||
|
} catch (error) {
|
||||||
|
// Handle invalid JSON if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page < 1 || limit < 1) {
|
||||||
|
throw new ApiError(400, 'Invalid pagination values');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch filtered landing page details
|
||||||
|
const result = await filteredLandingPageService.getFilteredLandingPageAllDetails(
|
||||||
|
userId,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
countryName,
|
||||||
|
stateName,
|
||||||
|
cityName,
|
||||||
|
userLat,
|
||||||
|
userLong,
|
||||||
|
activityTypeXids
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Filtered landing page data retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { UserService } from '../../services/user.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
|
||||||
|
const userService = new UserService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
// Extract token from headers
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify token and get user info
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch user with their HostHeader stepper info
|
||||||
|
const result = await userService.getAllBucketActivities(
|
||||||
|
userId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Data retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -27,16 +27,16 @@ export const handler = safeHandler(async (
|
|||||||
const longParam = event.queryStringParameters?.long ?? event.queryStringParameters?.lng ?? event.queryStringParameters?.longitude;
|
const longParam = event.queryStringParameters?.long ?? event.queryStringParameters?.lng ?? event.queryStringParameters?.longitude;
|
||||||
const radiusParam = event.queryStringParameters?.radiusKm ?? event.queryStringParameters?.radius;
|
const radiusParam = event.queryStringParameters?.radiusKm ?? event.queryStringParameters?.radius;
|
||||||
|
|
||||||
if (!latParam || !longParam || !radiusParam) {
|
const userLat = latParam ? Number(latParam) : undefined;
|
||||||
throw new ApiError(400, 'lat, long and radiusKm (in km) are required as query parameters');
|
const userLong = longParam ? Number(longParam) : undefined;
|
||||||
}
|
const radiusKm = radiusParam ? Number(radiusParam) : 15; // default 15km
|
||||||
|
|
||||||
const userLat = Number(latParam);
|
if (
|
||||||
const userLong = Number(longParam);
|
(userLat !== undefined && Number.isNaN(userLat)) ||
|
||||||
const radiusKm = Number(radiusParam);
|
(userLong !== undefined && Number.isNaN(userLong)) ||
|
||||||
|
Number.isNaN(radiusKm)
|
||||||
if (Number.isNaN(userLat) || Number.isNaN(userLong) || Number.isNaN(radiusKm)) {
|
) {
|
||||||
throw new ApiError(400, 'lat, long and radiusKm must be valid numbers');
|
throw new ApiError(400, 'Invalid lat/long values');
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = Number(event.queryStringParameters?.page ?? 1);
|
const page = Number(event.queryStringParameters?.page ?? 1);
|
||||||
|
|||||||
@@ -26,19 +26,11 @@ export const handler = safeHandler(async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract query parameters for search
|
// Extract query parameters for search
|
||||||
const activityTitle = event.queryStringParameters?.activityTitle?.trim();
|
|
||||||
const activityType = event.queryStringParameters?.activityType?.trim();
|
const activityType = event.queryStringParameters?.activityType?.trim();
|
||||||
const checkInCity = event.queryStringParameters?.checkInCity?.trim();
|
|
||||||
|
|
||||||
// At least one search parameter should be provided
|
|
||||||
if (!activityTitle && !activityType && !checkInCity) {
|
|
||||||
throw new ApiError(400, 'At least one search parameter (activityTitle, activityType, or checkInCity) must be provided');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch activities based on search criteria
|
// Fetch activities based on search criteria
|
||||||
const result = await userService.searchActivities(
|
const result = await userService.searchActivities(
|
||||||
userId,
|
activityType
|
||||||
{ activityTitle, activityType, checkInCity }
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { UserService } from '../../services/user.service';
|
||||||
|
|
||||||
|
const userService = new UserService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
// Extract token from headers
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate user using verifyUserToken
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = userInfo.id;
|
||||||
|
|
||||||
|
if (Number.isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'User id must be a number');
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await userService.getUserById(userId);
|
||||||
|
if (!user) {
|
||||||
|
throw new ApiError(404, 'User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse request body
|
||||||
|
let body: { activityXid: number; isBucket: boolean; bucketTypeName: string; };
|
||||||
|
|
||||||
|
try {
|
||||||
|
body = event.body ? JSON.parse(event.body) : {};
|
||||||
|
} catch (error) {
|
||||||
|
throw new ApiError(400, 'Invalid JSON in request body');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { activityXid, isBucket, bucketTypeName } = body;
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (
|
||||||
|
typeof activityXid !== 'number' ||
|
||||||
|
typeof isBucket !== 'boolean' ||
|
||||||
|
!bucketTypeName
|
||||||
|
) {
|
||||||
|
throw new ApiError(400, 'Required fields missing or invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from bucket/interested
|
||||||
|
const counts = await userService.removeFromBucketInterested(userId, isBucket, bucketTypeName, activityXid);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: `Activity removed from ${isBucket ? 'bucket' : 'interested'} successfully`,
|
||||||
|
data: {
|
||||||
|
bucketCount: counts.bucketCount,
|
||||||
|
interestedCount: counts.interestedCount,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -86,9 +86,10 @@ export const handler = safeHandler(
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Access token generated successfully',
|
message: 'Access token generated successfully',
|
||||||
|
data: {
|
||||||
accessToken: newAccessToken.access.token,
|
accessToken: newAccessToken.access.token,
|
||||||
accessTokenExpires: newAccessToken.access.expires,
|
accessTokenExpires: newAccessToken.access.expires,
|
||||||
data: null,
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,16 +30,17 @@ export const handler = safeHandler(async (
|
|||||||
const transactionResult = await prismaClient.$transaction(async (tx) => {
|
const transactionResult = await prismaClient.$transaction(async (tx) => {
|
||||||
const user = await tx.user.findFirst({
|
const user = await tx.user.findFirst({
|
||||||
where: { mobileNumber: mobileNumber, isActive: true, userStatus: USER_STATUS.ACTIVE },
|
where: { mobileNumber: mobileNumber, isActive: true, userStatus: USER_STATUS.ACTIVE },
|
||||||
select: { id: true, userPasscode: true, mobileNumber: true },
|
select: { id: true, userPasscode: true, mobileNumber: true, firstName: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
let newUserLocal;
|
let newUserLocal;
|
||||||
let isNewUser = false;
|
let isNewUser = false;
|
||||||
|
|
||||||
|
|
||||||
if (user && !user.userPasscode) {
|
if (user && (!user.userPasscode || !user.firstName)) {
|
||||||
// reuse existing invited user record
|
// reuse existing invited user record
|
||||||
newUserLocal = user;
|
newUserLocal = user;
|
||||||
|
isNewUser = true;
|
||||||
} else if (user) {
|
} else if (user) {
|
||||||
// Fully registered user already exists
|
// Fully registered user already exists
|
||||||
newUserLocal = user;
|
newUserLocal = user;
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { UserService } from '../../services/user.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
|
||||||
|
const userService = new UserService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'This is a protected route. Please provide a valid token.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchQuery = event.queryStringParameters?.searchQuery ?? '';
|
||||||
|
const result = await userService.searchConnectionPeople(userId, searchQuery);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Connection people retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { ItineraryService } from '../../services/itinerary.service';
|
||||||
|
|
||||||
|
const itineraryService = new ItineraryService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'This is a protected route. Please provide a valid token.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await itineraryService.getAllUserSavedItineraries(userId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Saved itineraries retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { ItineraryService } from '../../services/itinerary.service';
|
||||||
|
|
||||||
|
const itineraryService = new ItineraryService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'This is a protected route. Please provide a valid token.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || Number.isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
let body: Record<string, any> = {};
|
||||||
|
if (event.body) {
|
||||||
|
try {
|
||||||
|
body = JSON.parse(event.body);
|
||||||
|
} catch {
|
||||||
|
throw new ApiError(400, 'Invalid JSON body');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
userLat: Number(body.userLat),
|
||||||
|
userLong: Number(body.userLong),
|
||||||
|
startDate: body.startDate,
|
||||||
|
endDate: body.endDate,
|
||||||
|
startTime: body.startTime,
|
||||||
|
endTime: body.endTime,
|
||||||
|
energyLevelXid:
|
||||||
|
body.energyLevelXid !== undefined && body.energyLevelXid !== null
|
||||||
|
? Number(body.energyLevelXid)
|
||||||
|
: undefined,
|
||||||
|
entryTypeXid: Number(body.entryTypeXid),
|
||||||
|
groupCount:
|
||||||
|
body.groupCount !== undefined && body.groupCount !== null
|
||||||
|
? Number(body.groupCount)
|
||||||
|
: undefined,
|
||||||
|
page: body.page !== undefined ? Number(body.page) : 1,
|
||||||
|
limit: body.limit !== undefined ? Number(body.limit) : 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
Number.isNaN(payload.userLat) ||
|
||||||
|
Number.isNaN(payload.userLong) ||
|
||||||
|
!payload.startDate ||
|
||||||
|
!payload.endDate ||
|
||||||
|
!payload.startTime ||
|
||||||
|
!payload.endTime ||
|
||||||
|
(payload.energyLevelXid !== undefined &&
|
||||||
|
Number.isNaN(payload.energyLevelXid)) ||
|
||||||
|
Number.isNaN(payload.entryTypeXid) ||
|
||||||
|
(payload.groupCount !== undefined && Number.isNaN(payload.groupCount)) ||
|
||||||
|
Number.isNaN(payload.page) ||
|
||||||
|
Number.isNaN(payload.limit)
|
||||||
|
) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'userLat, userLong, startDate, endDate, startTime, endTime, entryTypeXid, page and limit are required. energyLevelXid is optional.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await itineraryService.getMatchingBucketInterestedActivities(
|
||||||
|
userId,
|
||||||
|
payload,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Matching itinerary activities retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { ItineraryService } from '../../services/itinerary.service';
|
||||||
|
|
||||||
|
const itineraryService = new ItineraryService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'This is a protected route. Please provide a valid token.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await itineraryService.getUserItineraryDetails(userId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Itinerary details retrieved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
145
src/modules/user/handlers/itinerary/saveUserItinerary.ts
Normal file
145
src/modules/user/handlers/itinerary/saveUserItinerary.ts
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||||
|
import { prismaClient } from '../../../../common/database/prisma.lambda.service';
|
||||||
|
import { verifyUserToken } from '../../../../common/middlewares/jwt/authForUser';
|
||||||
|
import { safeHandler } from '../../../../common/utils/handlers/safeHandler';
|
||||||
|
import ApiError from '../../../../common/utils/helper/ApiError';
|
||||||
|
import { ItineraryService } from '../../services/itinerary.service';
|
||||||
|
|
||||||
|
const itineraryService = new ItineraryService(prismaClient);
|
||||||
|
|
||||||
|
export const handler = safeHandler(async (
|
||||||
|
event: APIGatewayProxyEvent,
|
||||||
|
context?: Context,
|
||||||
|
): Promise<APIGatewayProxyResult> => {
|
||||||
|
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||||
|
if (!token) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'This is a protected route. Please provide a valid token.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userInfo = await verifyUserToken(token);
|
||||||
|
const userId = Number(userInfo.id);
|
||||||
|
|
||||||
|
if (!userId || Number.isNaN(userId)) {
|
||||||
|
throw new ApiError(400, 'Invalid user ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
let body: Record<string, any> = {};
|
||||||
|
if (event.body) {
|
||||||
|
try {
|
||||||
|
body = JSON.parse(event.body);
|
||||||
|
} catch {
|
||||||
|
throw new ApiError(400, 'Invalid JSON body');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const activities = Array.isArray(body.activities) ? body.activities : [];
|
||||||
|
|
||||||
|
if (!body.startDate || !body.endDate || !body.startTime || !body.endTime) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'startDate, endDate, startTime and endTime are required.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activities.length) {
|
||||||
|
throw new ApiError(400, 'At least one activity is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const activity of activities) {
|
||||||
|
if (
|
||||||
|
!activity.activityXid ||
|
||||||
|
!activity.venueXid ||
|
||||||
|
!activity.scheduleHeaderXid ||
|
||||||
|
!activity.modeOfTravel ||
|
||||||
|
activity.travelTimeBetweenPointsMins === undefined ||
|
||||||
|
activity.travelTimeBetweenPointsMins === null
|
||||||
|
) {
|
||||||
|
throw new ApiError(
|
||||||
|
400,
|
||||||
|
'Each activity must include activityXid, venueXid, scheduleHeaderXid, modeOfTravel and travelTimeBetweenPointsMins.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
title: body.title,
|
||||||
|
startDate: body.startDate,
|
||||||
|
endDate: body.endDate,
|
||||||
|
startTime: body.startTime,
|
||||||
|
endTime: body.endTime,
|
||||||
|
activities: activities.map((activity: any) => ({
|
||||||
|
activityXid: Number(activity.activityXid),
|
||||||
|
venueXid: Number(activity.venueXid),
|
||||||
|
scheduleHeaderXid: Number(activity.scheduleHeaderXid),
|
||||||
|
modeOfTravel: activity.modeOfTravel,
|
||||||
|
travelTimeBetweenPointsMins: Number(
|
||||||
|
activity.travelTimeBetweenPointsMins,
|
||||||
|
),
|
||||||
|
kmForNextPoint:
|
||||||
|
activity.kmForNextPoint !== undefined &&
|
||||||
|
activity.kmForNextPoint !== null
|
||||||
|
? Number(activity.kmForNextPoint)
|
||||||
|
: undefined,
|
||||||
|
occurenceDate: activity.occurenceDate,
|
||||||
|
selectedStartTime: activity.selectedStartTime,
|
||||||
|
selectedEndTime: activity.selectedEndTime,
|
||||||
|
itineraryType: activity.itineraryType,
|
||||||
|
paxCount:
|
||||||
|
activity.paxCount !== undefined && activity.paxCount !== null
|
||||||
|
? Number(activity.paxCount)
|
||||||
|
: undefined,
|
||||||
|
totalAmount:
|
||||||
|
activity.totalAmount !== undefined && activity.totalAmount !== null
|
||||||
|
? Number(activity.totalAmount)
|
||||||
|
: undefined,
|
||||||
|
locationLat:
|
||||||
|
activity.locationLat !== undefined && activity.locationLat !== null
|
||||||
|
? Number(activity.locationLat)
|
||||||
|
: undefined,
|
||||||
|
locationLong:
|
||||||
|
activity.locationLong !== undefined && activity.locationLong !== null
|
||||||
|
? Number(activity.locationLong)
|
||||||
|
: undefined,
|
||||||
|
locationAddress: activity.locationAddress,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.activities.some(
|
||||||
|
(activity) =>
|
||||||
|
Number.isNaN(activity.activityXid) ||
|
||||||
|
Number.isNaN(activity.venueXid) ||
|
||||||
|
Number.isNaN(activity.scheduleHeaderXid) ||
|
||||||
|
Number.isNaN(activity.travelTimeBetweenPointsMins) ||
|
||||||
|
(activity.kmForNextPoint !== undefined &&
|
||||||
|
Number.isNaN(activity.kmForNextPoint)) ||
|
||||||
|
(activity.paxCount !== undefined && Number.isNaN(activity.paxCount)) ||
|
||||||
|
(activity.totalAmount !== undefined &&
|
||||||
|
Number.isNaN(activity.totalAmount)) ||
|
||||||
|
(activity.locationLat !== undefined &&
|
||||||
|
Number.isNaN(activity.locationLat)) ||
|
||||||
|
(activity.locationLong !== undefined &&
|
||||||
|
Number.isNaN(activity.locationLong)),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new ApiError(400, 'One or more numeric itinerary values are invalid.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await itineraryService.saveUserItinerary(userId, payload);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: 201,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
message: 'Itinerary saved successfully',
|
||||||
|
data: result,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
938
src/modules/user/services/filteredLandingPage.service.ts
Normal file
938
src/modules/user/services/filteredLandingPage.service.ts
Normal file
@@ -0,0 +1,938 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
import { getPresignedUrl } from '../../../common/middlewares/aws/getPreSignedUrl';
|
||||||
|
import {
|
||||||
|
ACTIVITY_AM_INTERNAL_STATUS,
|
||||||
|
ACTIVITY_INTERNAL_STATUS,
|
||||||
|
} from '../../../common/utils/constants/host.constant';
|
||||||
|
import config from '../../../config/config';
|
||||||
|
|
||||||
|
const bucket = config.aws.bucketName;
|
||||||
|
|
||||||
|
const attachPresignedUrl = async (file: string | null | undefined) => {
|
||||||
|
if (!file) return null;
|
||||||
|
|
||||||
|
const key = file.startsWith('http')
|
||||||
|
? new URL(file).pathname.replace(/^\/+/, '')
|
||||||
|
: file;
|
||||||
|
|
||||||
|
return getPresignedUrl(bucket, key);
|
||||||
|
};
|
||||||
|
|
||||||
|
const attachMediaWithPresignedUrl = async (mediaArr: any[] = []) => {
|
||||||
|
return Promise.all(
|
||||||
|
mediaArr.map(async (m) => ({
|
||||||
|
...m,
|
||||||
|
presignedUrl: await attachPresignedUrl(m.mediaFileName),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FilteredLandingPageService {
|
||||||
|
constructor(private readonly prisma: PrismaClient) { }
|
||||||
|
|
||||||
|
normalizeName = (name: string): string => {
|
||||||
|
return name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9\s]/g, '')
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
findOrCreateLocation = async (
|
||||||
|
countryName: string,
|
||||||
|
stateName: string,
|
||||||
|
cityName: string,
|
||||||
|
tx: any,
|
||||||
|
) => {
|
||||||
|
const normalizedCountry = this.normalizeName(countryName);
|
||||||
|
const normalizedState = this.normalizeName(stateName);
|
||||||
|
const normalizedCity = this.normalizeName(cityName);
|
||||||
|
|
||||||
|
let country = await tx.countries.findFirst({
|
||||||
|
where: {
|
||||||
|
countryName: { contains: normalizedCountry, mode: 'insensitive' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!country) {
|
||||||
|
country = await tx.countries.create({
|
||||||
|
data: {
|
||||||
|
countryName: countryName.trim(),
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = await tx.states.findFirst({
|
||||||
|
where: {
|
||||||
|
countryXid: country.id,
|
||||||
|
stateName: { contains: normalizedState, mode: 'insensitive' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!state) {
|
||||||
|
state = await tx.states.create({
|
||||||
|
data: {
|
||||||
|
countryXid: country.id,
|
||||||
|
stateName: stateName.trim(),
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let city = await tx.cities.findFirst({
|
||||||
|
where: {
|
||||||
|
stateXid: state.id,
|
||||||
|
cityName: { contains: normalizedCity, mode: 'insensitive' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!city) {
|
||||||
|
city = await tx.cities.create({
|
||||||
|
data: {
|
||||||
|
stateXid: state.id,
|
||||||
|
cityName: cityName.trim(),
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
countryXid: country.id,
|
||||||
|
stateXid: state.id,
|
||||||
|
cityXid: city.id,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// attachMediaWithPresignedUrl = async (mediaArr = []) => {
|
||||||
|
// return (
|
||||||
|
// await Promise.all(
|
||||||
|
// mediaArr.map(async (m) => {
|
||||||
|
// return {
|
||||||
|
// ...m,
|
||||||
|
// presignedUrl: await this.attachPresignedUrl(m.mediaFileName),
|
||||||
|
// };
|
||||||
|
// }),
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
calculateDistance = (
|
||||||
|
lat1: number | null,
|
||||||
|
lon1: number | null,
|
||||||
|
lat2: number | null,
|
||||||
|
lon2: number | null,
|
||||||
|
) => {
|
||||||
|
if (!lat1 || !lon1 || !lat2 || !lon2) return null;
|
||||||
|
|
||||||
|
const R = 6371; // km
|
||||||
|
const dLat = ((lat2 - lat1) * Math.PI) / 180;
|
||||||
|
const dLon = ((lon2 - lon1) * Math.PI) / 180;
|
||||||
|
|
||||||
|
const a =
|
||||||
|
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos((lat1 * Math.PI) / 180) *
|
||||||
|
Math.cos((lat2 * Math.PI) / 180) *
|
||||||
|
Math.sin(dLon / 2) *
|
||||||
|
Math.sin(dLon / 2);
|
||||||
|
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
const distance = R * c;
|
||||||
|
|
||||||
|
// return distance rounded to 2 decimals
|
||||||
|
return Number(distance.toFixed(2));
|
||||||
|
};
|
||||||
|
|
||||||
|
async rankAndPaginateActivities(
|
||||||
|
tx: any,
|
||||||
|
whereClause: any,
|
||||||
|
page: number,
|
||||||
|
limit: number,
|
||||||
|
connectionInterestMap: Map<number, number>,
|
||||||
|
) {
|
||||||
|
const skip = (page - 1) * limit;
|
||||||
|
|
||||||
|
// Get total count
|
||||||
|
const totalCount = await tx.activities.count({ where: whereClause });
|
||||||
|
|
||||||
|
// Fetch activities with ranking metadata
|
||||||
|
const activities = await tx.activities.findMany({
|
||||||
|
where: whereClause,
|
||||||
|
skip,
|
||||||
|
take: limit,
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTitle: true,
|
||||||
|
sustainabilityScore: true,
|
||||||
|
totalScore: true,
|
||||||
|
activityType: {
|
||||||
|
select: {
|
||||||
|
interestXid: true,
|
||||||
|
energyLevel: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
energyLevelName: true,
|
||||||
|
energyColor: true,
|
||||||
|
energyIcon: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivitiesMedia: {
|
||||||
|
where: { isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
mediaFileName: true,
|
||||||
|
mediaType: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Fetch ranking metadata
|
||||||
|
ItineraryActivities: {
|
||||||
|
select: {
|
||||||
|
ActivityFeedbacks: {
|
||||||
|
select: { activityStars: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivityVenues: {
|
||||||
|
select: {
|
||||||
|
ActivityPrices: {
|
||||||
|
select: { sellPrice: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort and format
|
||||||
|
const sortedActivities = activities
|
||||||
|
.map((act) => {
|
||||||
|
const feedbacks = act.ItineraryActivities.flatMap(
|
||||||
|
(ia) => ia.ActivityFeedbacks,
|
||||||
|
);
|
||||||
|
const totalStars = feedbacks.reduce(
|
||||||
|
(sum, f) => sum + f.activityStars,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const avgRating =
|
||||||
|
feedbacks.length > 0 ? totalStars / feedbacks.length : 0;
|
||||||
|
const prices = act.ActivityVenues.flatMap((v) =>
|
||||||
|
v.ActivityPrices.map((p) => p.sellPrice),
|
||||||
|
).filter((p) => p !== null) as number[];
|
||||||
|
const minPrice = prices.length > 0 ? Math.min(...prices) : Infinity;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...act,
|
||||||
|
avgRating,
|
||||||
|
minPrice,
|
||||||
|
sustainabilityScore: act.sustainabilityScore ?? 0,
|
||||||
|
totalScore: act.totalScore ?? 0,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (b.avgRating !== a.avgRating) return b.avgRating - a.avgRating;
|
||||||
|
if (a.minPrice !== b.minPrice) return a.minPrice - b.minPrice;
|
||||||
|
if (b.sustainabilityScore !== a.sustainabilityScore)
|
||||||
|
return b.sustainabilityScore - a.sustainabilityScore;
|
||||||
|
return b.totalScore - a.totalScore;
|
||||||
|
});
|
||||||
|
|
||||||
|
const formattedActivities = await Promise.all(
|
||||||
|
sortedActivities.map(async (activity) => ({
|
||||||
|
interestXid: activity.activityType.interestXid,
|
||||||
|
activityId: activity.id,
|
||||||
|
connectionInterestedCount:
|
||||||
|
connectionInterestMap.get(activity.id) ?? 0,
|
||||||
|
activityTitle: activity.activityTitle,
|
||||||
|
sustainabilityScore: activity.sustainabilityScore,
|
||||||
|
cheapestPrice: activity.minPrice === Infinity ? null : activity.minPrice,
|
||||||
|
distance: 0,
|
||||||
|
rating: activity.avgRating,
|
||||||
|
energyLevel: activity.activityType.energyLevel
|
||||||
|
? {
|
||||||
|
...activity.activityType.energyLevel,
|
||||||
|
presignedUrl: await attachPresignedUrl(
|
||||||
|
activity.activityType.energyLevel.energyIcon
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
totalCount,
|
||||||
|
hasMore: skip + limit < totalCount,
|
||||||
|
activities: formattedActivities,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFilteredLandingPageAllDetails(
|
||||||
|
userId: number,
|
||||||
|
page: number,
|
||||||
|
limit: number,
|
||||||
|
countryName: string,
|
||||||
|
stateName: string,
|
||||||
|
cityName: string,
|
||||||
|
userLat: string,
|
||||||
|
userLong: string,
|
||||||
|
activityTypeXids?: number[],
|
||||||
|
) {
|
||||||
|
const data = await this.prisma.$transaction(async (tx) => {
|
||||||
|
const userAddressDetails = await tx.userAddressDetails.findFirst({
|
||||||
|
where: { userXid: userId, isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
address1: true,
|
||||||
|
address2: true,
|
||||||
|
pinCode: true,
|
||||||
|
locationName: true,
|
||||||
|
stateXid: true,
|
||||||
|
cityXid: true,
|
||||||
|
countryXid: true,
|
||||||
|
locationLat: true,
|
||||||
|
locationLong: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userLatitude = userAddressDetails?.locationLat ?? null;
|
||||||
|
const userLongitude = userAddressDetails?.locationLong ?? null;
|
||||||
|
|
||||||
|
let effectiveLocation: {
|
||||||
|
countryXid?: number | null;
|
||||||
|
stateXid?: number | null;
|
||||||
|
cityXid?: number | null;
|
||||||
|
} | null = null;
|
||||||
|
|
||||||
|
const hasRequestLocation = countryName && stateName && cityName;
|
||||||
|
|
||||||
|
if (hasRequestLocation) {
|
||||||
|
effectiveLocation = await this.findOrCreateLocation(
|
||||||
|
countryName!,
|
||||||
|
stateName!,
|
||||||
|
cityName!,
|
||||||
|
tx,
|
||||||
|
);
|
||||||
|
} else if (userAddressDetails) {
|
||||||
|
effectiveLocation = {
|
||||||
|
countryXid: userAddressDetails.countryXid,
|
||||||
|
stateXid: userAddressDetails.stateXid,
|
||||||
|
cityXid: userAddressDetails.cityXid,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const effectiveCountryXid = effectiveLocation?.countryXid ?? null;
|
||||||
|
const effectiveStateXid = effectiveLocation?.stateXid ?? null;
|
||||||
|
|
||||||
|
// Get all activity types for user interests, filtered by selected activity types if provided
|
||||||
|
const activityTypeWhere: any = {
|
||||||
|
isActive: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (activityTypeXids && activityTypeXids.length > 0) {
|
||||||
|
activityTypeWhere.id = { in: activityTypeXids };
|
||||||
|
}
|
||||||
|
|
||||||
|
const activityTypesWithInterests = await tx.activityTypes.findMany({
|
||||||
|
where: activityTypeWhere,
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTypeName: true,
|
||||||
|
interestXid: true,
|
||||||
|
interests: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
interestName: true,
|
||||||
|
interestColor: true,
|
||||||
|
interestImage: true,
|
||||||
|
displayOrder: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!activityTypesWithInterests.length) {
|
||||||
|
return {
|
||||||
|
userAddressDetails,
|
||||||
|
interests: [],
|
||||||
|
activityTypes: [],
|
||||||
|
otherStatesActivities: null,
|
||||||
|
overSeasActivities: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const userBucketInterested = await tx.userBucketInterested.findMany({
|
||||||
|
where: {
|
||||||
|
userXid: userId,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
activityXid: true,
|
||||||
|
isBucket: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userBucketActivityIds = userBucketInterested
|
||||||
|
.filter(u => u.isBucket)
|
||||||
|
.map(u => u.activityXid);
|
||||||
|
|
||||||
|
const userInterestedActivityIds = userBucketInterested
|
||||||
|
.filter(u => !u.isBucket)
|
||||||
|
.map(u => u.activityXid);
|
||||||
|
|
||||||
|
const allUserExcludedActivityIds = userBucketInterested.map(
|
||||||
|
u => u.activityXid,
|
||||||
|
);
|
||||||
|
|
||||||
|
const userConnectionDetails = await tx.connectDetails.findMany({
|
||||||
|
where: { userXid: userId, isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
schoolCompanyXid: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const otherConnectionUsers = await tx.connectDetails.findMany({
|
||||||
|
where: { userXid: { notIn: [userId] }, isActive: true, schoolCompanyXid: { in: userConnectionDetails.map((u) => u.schoolCompanyXid) } },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
userXid: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const connectionUserIds =
|
||||||
|
otherConnectionUsers.length > 0
|
||||||
|
? otherConnectionUsers.map(u => u.userXid)
|
||||||
|
: [-1];
|
||||||
|
|
||||||
|
const connectionInterestByActivity = await tx.userBucketInterested.groupBy({
|
||||||
|
by: ['activityXid'],
|
||||||
|
where: {
|
||||||
|
userXid: { in: connectionUserIds },
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
_count: {
|
||||||
|
activityXid: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const connectionInterestMap = new Map(
|
||||||
|
connectionInterestByActivity.map(item => [
|
||||||
|
item.activityXid,
|
||||||
|
item._count.activityXid,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
const skip = (page - 1) * limit;
|
||||||
|
|
||||||
|
// Group activity types by interest
|
||||||
|
const activityTypesByInterest = activityTypesWithInterests.reduce((acc, at) => {
|
||||||
|
if (!acc[at.interestXid]) {
|
||||||
|
acc[at.interestXid] = {
|
||||||
|
interest: at.interests,
|
||||||
|
activityTypes: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
acc[at.interestXid].activityTypes.push({
|
||||||
|
activityTypeId: at.id,
|
||||||
|
activityTypeName: at.activityTypeName,
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, {} as any);
|
||||||
|
|
||||||
|
// Fetch activities for each activity type with excluded activities filter
|
||||||
|
const activitiesByActivityType = await Promise.all(
|
||||||
|
activityTypesWithInterests.map(async (activityType) => {
|
||||||
|
const activities = await tx.activities.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
activityTypeXid: activityType.id,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
skip,
|
||||||
|
take: limit,
|
||||||
|
orderBy: { id: 'desc' },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTitle: true,
|
||||||
|
activityDurationMins: true,
|
||||||
|
sustainabilityScore: true,
|
||||||
|
checkInLat: true,
|
||||||
|
checkInLong: true,
|
||||||
|
activityType: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTypeName: true,
|
||||||
|
interestXid: true,
|
||||||
|
energyLevel: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
energyLevelName: true,
|
||||||
|
energyColor: true,
|
||||||
|
energyIcon: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivityVenues: {
|
||||||
|
select: {
|
||||||
|
ActivityPrices: {
|
||||||
|
select: {
|
||||||
|
sellPrice: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivitiesMedia: {
|
||||||
|
where: { isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
mediaFileName: true,
|
||||||
|
mediaType: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const formattedActivities = await Promise.all(
|
||||||
|
activities.map(async (activity) => {
|
||||||
|
const cheapestPrice =
|
||||||
|
activity.ActivityVenues.flatMap((v) => v.ActivityPrices)
|
||||||
|
.map((p) => p.sellPrice)
|
||||||
|
.filter(Boolean)
|
||||||
|
.sort((a, b) => a - b)[0] ?? null;
|
||||||
|
|
||||||
|
const distance = this.calculateDistance(
|
||||||
|
userLatitude,
|
||||||
|
userLongitude,
|
||||||
|
activity.checkInLat,
|
||||||
|
activity.checkInLong,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
activityId: activity.id,
|
||||||
|
connectionInterestedCount:
|
||||||
|
connectionInterestMap.get(activity.id) ?? 0,
|
||||||
|
activityTitle: activity.activityTitle,
|
||||||
|
activityDurationMins: activity.activityDurationMins,
|
||||||
|
sustainabilityScore: activity.sustainabilityScore,
|
||||||
|
cheapestPrice,
|
||||||
|
distance,
|
||||||
|
rating: 0,
|
||||||
|
energyLevel: activity.activityType.energyLevel
|
||||||
|
? {
|
||||||
|
...activity.activityType.energyLevel,
|
||||||
|
presignedUrl: await attachPresignedUrl(
|
||||||
|
activity.activityType.energyLevel.energyIcon
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
activityTypeId: activityType.id,
|
||||||
|
activityTypeName: activityType.activityTypeName,
|
||||||
|
interestXid: activityType.interestXid,
|
||||||
|
activities: formattedActivities,
|
||||||
|
pagination: {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
hasMore: formattedActivities.length === limit,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Group by interests for the final structure
|
||||||
|
const interestsWithActivities = await Promise.all(
|
||||||
|
Object.values(activityTypesByInterest).map(async (interestGroup: any) => {
|
||||||
|
// collect all activities belonging to this interest
|
||||||
|
const activitiesForInterest = activitiesByActivityType
|
||||||
|
.filter(a => a.interestXid === interestGroup.interest.id)
|
||||||
|
.flatMap(a => a.activities);
|
||||||
|
|
||||||
|
return {
|
||||||
|
interestId: interestGroup.interest.id,
|
||||||
|
interestName: interestGroup.interest.interestName,
|
||||||
|
interestColor: interestGroup.interest.interestColor,
|
||||||
|
interestImage: interestGroup.interest.interestImage,
|
||||||
|
interestImagePresignedUrl: await attachPresignedUrl(
|
||||||
|
interestGroup.interest.interestImage
|
||||||
|
),
|
||||||
|
displayOrder: interestGroup.interest.displayOrder,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
hasMore: activitiesForInterest.length === limit,
|
||||||
|
activities: activitiesForInterest
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Most Hyped Activities with filtering
|
||||||
|
const mostHypedGrouped = await tx.userBucketInterested.groupBy({
|
||||||
|
by: ['activityXid'],
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
isBucket: false,
|
||||||
|
activityXid: {
|
||||||
|
notIn: allUserExcludedActivityIds.length ? allUserExcludedActivityIds : [-1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
_count: {
|
||||||
|
activityXid: true,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
_count: {
|
||||||
|
activityXid: 'desc',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter most hyped activities by activity type if provided
|
||||||
|
let filteredMostHypedActivityIds = mostHypedGrouped.map((a) => a.activityXid);
|
||||||
|
|
||||||
|
if (activityTypeXids && activityTypeXids.length > 0) {
|
||||||
|
const activitiesWithTypes = await tx.activities.findMany({
|
||||||
|
where: {
|
||||||
|
id: { in: filteredMostHypedActivityIds },
|
||||||
|
activityTypeXid: { in: activityTypeXids },
|
||||||
|
},
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
filteredMostHypedActivityIds = activitiesWithTypes.map(a => a.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalMostHypedGrouped = mostHypedGrouped
|
||||||
|
.filter(group => filteredMostHypedActivityIds.includes(group.activityXid))
|
||||||
|
.slice(skip, skip + limit);
|
||||||
|
|
||||||
|
const totalHypedActivities = filteredMostHypedActivityIds.length;
|
||||||
|
const mostHypedActivityIds = finalMostHypedGrouped.map((a) => a.activityXid);
|
||||||
|
|
||||||
|
const mostHypedActivitiesRaw = await tx.activities.findMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: mostHypedActivityIds,
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTitle: true,
|
||||||
|
sustainabilityScore: true,
|
||||||
|
totalScore: true,
|
||||||
|
activityType: {
|
||||||
|
select: {
|
||||||
|
energyLevel: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
energyLevelName: true,
|
||||||
|
energyColor: true,
|
||||||
|
energyIcon: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivitiesMedia: {
|
||||||
|
where: { isActive: true },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
mediaFileName: true,
|
||||||
|
mediaType: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ItineraryActivities: {
|
||||||
|
select: {
|
||||||
|
ActivityFeedbacks: {
|
||||||
|
select: { activityStars: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ActivityVenues: {
|
||||||
|
select: {
|
||||||
|
ActivityPrices: {
|
||||||
|
select: { sellPrice: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort Most Hyped by the 4 criteria
|
||||||
|
const mostHypedSorted = mostHypedActivitiesRaw
|
||||||
|
.map((act) => {
|
||||||
|
const feedbacks = act.ItineraryActivities.flatMap(
|
||||||
|
(ia) => ia.ActivityFeedbacks,
|
||||||
|
);
|
||||||
|
const totalStars = feedbacks.reduce(
|
||||||
|
(sum, f) => sum + f.activityStars,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const avgRating =
|
||||||
|
feedbacks.length > 0 ? totalStars / feedbacks.length : 0;
|
||||||
|
const prices = act.ActivityVenues.flatMap((v) =>
|
||||||
|
v.ActivityPrices.map((p) => p.sellPrice),
|
||||||
|
).filter((p) => p !== null) as number[];
|
||||||
|
const minPrice = prices.length > 0 ? Math.min(...prices) : Infinity;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...act,
|
||||||
|
avgRating,
|
||||||
|
minPrice,
|
||||||
|
sustainabilityScore: act.sustainabilityScore ?? 0,
|
||||||
|
totalScore: act.totalScore ?? 0,
|
||||||
|
hypeCount:
|
||||||
|
finalMostHypedGrouped.find((g) => g.activityXid === act.id)?._count
|
||||||
|
.activityXid ?? 0,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (b.avgRating !== a.avgRating) return b.avgRating - a.avgRating;
|
||||||
|
if (a.minPrice !== b.minPrice) return a.minPrice - b.minPrice;
|
||||||
|
if (b.sustainabilityScore !== a.sustainabilityScore)
|
||||||
|
return b.sustainabilityScore - a.sustainabilityScore;
|
||||||
|
return b.totalScore - a.totalScore;
|
||||||
|
});
|
||||||
|
|
||||||
|
const mostHypedActivities = await Promise.all(
|
||||||
|
mostHypedSorted.map(async (activity) => ({
|
||||||
|
activityId: activity.id,
|
||||||
|
activityTitle: activity.activityTitle,
|
||||||
|
connectionInterestedCount:
|
||||||
|
connectionInterestMap.get(activity.id) ?? 0,
|
||||||
|
hypeCount: activity.hypeCount,
|
||||||
|
distance: 0,
|
||||||
|
rating: 0,
|
||||||
|
energyLevel: activity.activityType.energyLevel
|
||||||
|
? {
|
||||||
|
...activity.activityType.energyLevel,
|
||||||
|
presignedUrl: await attachPresignedUrl(
|
||||||
|
activity.activityType.energyLevel.energyIcon
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
media: await attachMediaWithPresignedUrl(activity.ActivitiesMedia),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
const formattedMostHypedActivities = {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
totalCount: totalHypedActivities,
|
||||||
|
hasMore: skip + limit < totalHypedActivities,
|
||||||
|
activities: mostHypedActivities,
|
||||||
|
};
|
||||||
|
|
||||||
|
// New Arrivals with filtering
|
||||||
|
const newArrivalsWhere: any = {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
createdAt: { gte: new Date(Date.now() - 31 * 24 * 60 * 60 * 1000) },
|
||||||
|
};
|
||||||
|
|
||||||
|
if (activityTypeXids && activityTypeXids.length > 0) {
|
||||||
|
newArrivalsWhere.activityTypeXid = { in: activityTypeXids };
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedNewArrivalsActivities = await this.rankAndPaginateActivities(
|
||||||
|
tx,
|
||||||
|
newArrivalsWhere,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
connectionInterestMap
|
||||||
|
);
|
||||||
|
|
||||||
|
// Other States Activities with filtering
|
||||||
|
const otherStatesWhere: any = {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (effectiveCountryXid) {
|
||||||
|
otherStatesWhere.checkInCountryXid = effectiveCountryXid;
|
||||||
|
}
|
||||||
|
if (effectiveStateXid) {
|
||||||
|
otherStatesWhere.checkInStateXid = { not: effectiveStateXid };
|
||||||
|
}
|
||||||
|
if (activityTypeXids && activityTypeXids.length > 0) {
|
||||||
|
otherStatesWhere.activityTypeXid = { in: activityTypeXids };
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedOtherStatesActivities = await this.rankAndPaginateActivities(
|
||||||
|
tx,
|
||||||
|
otherStatesWhere,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
connectionInterestMap
|
||||||
|
);
|
||||||
|
|
||||||
|
// Random Activities with filtering
|
||||||
|
const totalActiveCount = await tx.activities.count({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
deletedAt: null,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
...(activityTypeXids && activityTypeXids.length > 0 && {
|
||||||
|
activityTypeXid: { in: activityTypeXids },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let randomActivities: any[] = [];
|
||||||
|
|
||||||
|
if (totalActiveCount > 0) {
|
||||||
|
const takeCount = Math.min(5, totalActiveCount);
|
||||||
|
|
||||||
|
const randomOffsets = new Set<number>();
|
||||||
|
while (randomOffsets.size < takeCount) {
|
||||||
|
randomOffsets.add(Math.floor(Math.random() * totalActiveCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomFetched = await Promise.all(
|
||||||
|
Array.from(randomOffsets).map((offset) =>
|
||||||
|
tx.activities.findFirst({
|
||||||
|
skip: offset,
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus:
|
||||||
|
ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus:
|
||||||
|
ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
deletedAt: null,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
...(activityTypeXids && activityTypeXids.length > 0 && {
|
||||||
|
activityTypeXid: { in: activityTypeXids },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
activityTitle: true,
|
||||||
|
ActivitiesMedia: {
|
||||||
|
where: { isActive: true, isCoverImage: true },
|
||||||
|
orderBy: { displayOrder: 'asc' },
|
||||||
|
take: 1,
|
||||||
|
select: {
|
||||||
|
mediaFileName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
randomActivities = await Promise.all(
|
||||||
|
randomFetched
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(async (activity) => {
|
||||||
|
const cover = activity!.ActivitiesMedia?.[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
activityId: activity!.id,
|
||||||
|
activityTitle: activity!.activityTitle,
|
||||||
|
coverImage: cover?.mediaFileName ?? null,
|
||||||
|
coverImagePresignedUrl: await attachPresignedUrl(
|
||||||
|
cover?.mediaFileName
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overseas Activities with filtering
|
||||||
|
const overseasWhere: any = {
|
||||||
|
isActive: true,
|
||||||
|
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_LISTED,
|
||||||
|
id: {
|
||||||
|
notIn: allUserExcludedActivityIds.length
|
||||||
|
? allUserExcludedActivityIds
|
||||||
|
: [-1],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (effectiveCountryXid) {
|
||||||
|
overseasWhere.checkInCountryXid = { not: effectiveCountryXid };
|
||||||
|
}
|
||||||
|
if (activityTypeXids && activityTypeXids.length > 0) {
|
||||||
|
overseasWhere.activityTypeXid = { in: activityTypeXids };
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedOverSeasActivities = await this.rankAndPaginateActivities(
|
||||||
|
tx,
|
||||||
|
overseasWhere,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
connectionInterestMap
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
userAddressDetails,
|
||||||
|
experiencesLogged: 0,
|
||||||
|
citiesDiscovered: 0,
|
||||||
|
loggedInNetworkCount: 0,
|
||||||
|
citiesInNetworkCount: 0,
|
||||||
|
rating: 0,
|
||||||
|
interestedCount: userInterestedActivityIds.length,
|
||||||
|
bucketCount: userBucketActivityIds.length,
|
||||||
|
pagination: {
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
},
|
||||||
|
randomActivities,
|
||||||
|
interests: interestsWithActivities,
|
||||||
|
otherStatesActivities: formattedOtherStatesActivities,
|
||||||
|
overSeasActivities: formattedOverSeasActivities,
|
||||||
|
newArrivalsActivities: formattedNewArrivalsActivities,
|
||||||
|
mostHypedActivities: formattedMostHypedActivities,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
1815
src/modules/user/services/itinerary.service.ts
Normal file
1815
src/modules/user/services/itinerary.service.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user