diff --git a/.env.sample b/.env.sample index 60d200e3..ea58f6b0 100644 --- a/.env.sample +++ b/.env.sample @@ -44,7 +44,7 @@ CLOUD_STORAGE_REGION = "ap-south-1" CLOUD_STORAGE_PROJECT = "sl-dev-project" // CSP project Id (required for gcloud CSP) CLOUD_ENDPOINT = https://a**.compat.objectstorage.ap-hyderabad-1.oraclecloud.com // CSP endpoint (required for oci) -DEFAULT_ORGANISATION_CODE = 1 // this default variable helps to get organistion details +DEFAULT_ORGANISATION_CODE = default_code // this default variable helps to get organistion details diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 241e64fe..1647cde1 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -14,7 +14,7 @@ env: jobs: docker-image-build-and-push: - if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/staging' + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index fddde5a5..b4c9ad68 100644 --- a/README.md +++ b/README.md @@ -13,1500 +13,175 @@ ![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) - - +
The Project building block facilitates the creation and engagement with micro-improvement projects. - -
- -# Supported Operating Systems - -- **Ubuntu (Recommended: Version 20 and above)** -- **Windows (Recommended: Version 11 and above)** -- **macOs (Recommended: Version 12 and above)** - -# Setup Options - -**Project services can be setup using two methods:** - -> Note : This guide outlines two setup methods, detailed below. For a quick, beginner-friendly setup and walkthrough of services, it is recommended to use the Dockerized Services & Dependencies setup with the Docker-Compose file. - -
Dockerized Services & Dependencies Using Docker-Compose File - -## Dockerized Services & Dependencies - -Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. - -## Prerequisites - -To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Ubuntu users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Ubuntu](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04). To install and use Nodejs in Ubuntu machine, you can follow instructions here: [How To Install Nodejs in Ubuntu](https://nodejs.org/en/download/package-manager). For Windows and MacOS users, you can refer to the Docker documentation for installation instructions: [Docker Compose Installation Guide](https://docs.docker.com/compose/install/). Once these prerequisites are in place, you're all set to get started with setting up the Project application. - -## Installation - -**Create project Directory:** Establish a directory titled **project**. - -> Example Command: `mkdir project && cd project/` - -> Note: All commands are run from the project directory. - -## Operating Systems: Linux / macOS - -> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this - -``` -for port in 3000 3001 3002 6000 5001 4000 9092 5432 7007 2181 2707 3569; do - if lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then - echo "Port $port is in use" - else - echo "Port $port is available" - fi -done -``` - -1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. - ` curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/mac-linux/setup_project.sh && chmod +x setup_project.sh && sudo ./setup_project.sh` - - > Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. - - **General Instructions :** - - 1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. - - 2. All docker containers can be stopped and removed by using below command. - ``` - sudo ./docker-compose-down.sh - ``` - 3. All services and dependencies can be started using below command. - ``` - sudo ./docker-compose-up.sh - ``` - - **Keep the current terminal session active, and kindly open a new terminal window within the project directory.** - -**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** - -## Operating Systems: Windows - -1. **Download Docker Compose File:** Retrieve the **[docker-compose-project.yml](https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml)** file from the Project service repository and save it to the project directory. - - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml - ``` - - > Note: All commands are run from the project directory. - -2. **Download Environment Files**: Using the OS specific commands given below, download environment files for all the services. - - - **Windows** - - ``` - curl -L ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/interface_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/entity_management_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/project_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/notification_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/scheduler_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/user_env ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/env.js - ``` - - > **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. - - > **Caution:** While the default values in the downloaded environment files enable the Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. - -3. **Download `replace_volume_path` Script File** - - - **Windows** - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/dockerized/scripts/windows/replace_volume_path.bat - ``` - -4. **Run `replace_volume_path` Script File** - - - **Windows** - - Run the script file either by double clicking it or by executing the following command from the terminal. - - ``` - replace_volume_path.bat - ``` - - > **Note**: The provided script file replaces the host path for the **portal** service container volume in the `docker-compose-project.yml` file with your current directory path. - > - > volumes: - > - > \- /home/shikshalokam/elevate/single-click/linux/env.js:/usr/src/app/www/assets/env/env.js - -5. **Download `docker-compose-up` & `docker-compose-down` Script Files** - - - **Windows** - - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/docker-compose-up.bat - ``` - - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/docker-compose-down.bat - ``` - -6. **Run All Services & Dependencies**:All services and dependencies can be started using the `docker-compose-up` script file. - - - **Windows** - - ``` - docker-compose-up.bat - ``` - - > Double-click the file or run the above command from the terminal. - - > **Note**: During the first Docker Compose run, the database, migration seeder files, and the script to set the default organization will be executed automatically. - -7. **Remove All Service & Dependency Containers**: - All docker containers can be stopped and removed by using the `docker-compose-down` file. +--- - - **Windows** +## ๐Ÿ’ป Supported Operating Systems - ``` - docker-compose-down.bat - ``` +- **Ubuntu** (Recommended: Version 20 and above) +- **Windows** (Recommended: Version 11 and above) +- **macOS** (Recommended: Version 12 and above) - > **Caution**: As per the default configuration in the `docker-compose-project.yml` file, using the `down` command will lead to data loss since the database container does not persist data. To persist data across `down` commands and subsequent container removals, refer to the "Persistence of Database Data in Docker Containers" section of this documentation. +--- -## Enable Citus Extension (Optional) +## โœจ Setup & Deployment Guide -User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. +This section outlines the different ways to set up the **Projects Service**. Please select the deployment environment and setup method that best suits your needs. -For more information, refer **[Citus Data](https://www.citusdata.com/)**. - -To enable the Citus extension for user services, follow these steps. - -1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. (Skip this for linux/macOs) - ``` - mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql - ``` -2. Set up the citus_setup file by following the steps given below. - - - **Ubuntu/Linux/Mac** - - 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. - ``` - sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user - ``` - - - **Windows** - 1. Download the `citus_setup.bat` file. - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/citus_setup.bat - ``` - 2. Enable Citus and set distribution columns for `user` database by running the `citus_setup.bat`with the following arguments. - ``` - citus_setup.bat user postgres://postgres:postgres@citus_master:5432/user - ``` - > **Note:** Since the `citus_setup.bat` file requires arguments, it must be run from a terminal. - -## Persistence Of Database Data In Docker Container (Optional) - -To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: - -1. **Modification Of The `docker-compose-project.yml` File:** - - Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: - - ```yaml - mongo: - image: 'mongo:4.4.14' - restart: 'always' - ports: - - '27017:27017' - networks: - - project_net - volumes: - - mongo-data:/data/db - logging: - driver: none - - citus: - image: citusdata/citus:11.2.0 - container_name: 'citus_master' - ports: - - 5432:5432 - volumes: - - citus-data:/var/lib/postgresql/data - ``` - -2. **Uncommenting Volume Names Under The Volumes Section:** - - Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: - - ```yaml - networks: - elevate_net: - external: false - - volumes: - citus-data: - mongo-data: - ``` - -By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. - -## Sample User Accounts Generation - -During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. - -In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. - -> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. - -- **Ubuntu/Linux/Mac** - - ``` - sudo ./insert_sample_data.sh user postgres://postgres:postgres@citus_master:5432/user - ``` - -- **Windows** - - 1. **Download The `sampleData.sql` Files:** - - ``` - mkdir sample-data\user 2>nul & ^ - curl -L "https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/sample-data/windows/user/sampleData.sql" -o sample-data\user\sampleData.sql - ``` - - 2. **Download The `insert_sample_data` Script File:** - - ``` - curl -L -o insert_sample_data.bat https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/dockerized/scripts/windows/insert_sample_data.bat - ``` - - 3. **Run The `insert_sample_data` Script File:** - - ``` - insert_sample_data.bat user postgres://postgres:postgres@citus_master:5432/user - ``` - - After successfully running the script mentioned above, the following user accounts will be created and available for login: - - | Email ID | Password | Role | - | ------------------------ | ---------- | ----------------------- | - | aaravpatel@example.com | Password1@ | State Education Officer | - | arunimareddy@example.com | Password1@ | State Education Officer | - | devikasingh@example.com | Password1@ | State Education Officer | - -## Sample Data Creation For Projects - -This step will guide us in implementing a sample project solution following the initial setup of the project service. - -1. **Insert Sample Data To Database:** - - - **Ubuntu/Linux/Mac** - - 1. Insert sample data by running the following command. - - ``` - sudo ./add_sample_project_entity_data.sh - ``` - - - **Windows** - - 1. Download `entity-project-sample-data.bat` Script File: - - ``` - curl -L ^ - -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/entity-project-sample-data.bat ^ - ``` - - 2. Make the setup file executable by running the following command. - - ``` - entity-project-sample-data.bat - ``` - -## Default Forms Creation for Portal Configuration - -This step inserts configuration forms into MongoDB, enabling or disabling features and fields on portal pages. - -#### Insert Forms Data into Database - -- **Ubuntu/Linux/Mac**: - - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/mac-linux/import_forms_mongo.sh && chmod +x import_forms_mongo.sh && sudo ./import_forms_mongo.sh mongodb://mongo:27017/elevate-project - ``` - -- **Windows**: - 1. Download the `import_forms_mongo.bat` file: - ```cmd - curl -L -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/import_forms_mongo.bat - ``` - 2. Run the script: - ```cmd - import_forms_mongo.bat mongodb://localhost:27017/elevate-project - ``` - -## Explore the Portal - -Once the services are up and the front-end app bundle is built successfully, navigate to **[localhost:7007](http://localhost:7007/)** to access the Project app. - -> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. - -
+---
-Natively Installed Services & Dependencies - -## PM2 Managed Services & Natively Installed Dependencies - -### System Requirements - -- **Node.jsยฎ:** v20 -- **PostgreSQL:** 16 -- **Apache Kafkaยฎ:** 3.5.0 -- **MongoDB:** 4.4.14 -- **Gotenberg:** 8.5.0 - -Expectation: Upon following the prescribed steps, you will achieve a fully operational ELEVATE-Project application setup. Both the portal and backend services are managed using PM2, with all dependencies installed natively on the host system. - -## Prerequisites - -Before setting up the following ELEVATE-Project application, dependencies given below should be installed and verified to be running. Refer to the steps given below to install them and verify. - -- **Ubuntu/Linux** - - 1. Download dependency management scripts: - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/check-dependencies.sh && \ - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/install-dependencies.sh && \ - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/uninstall-dependencies.sh && \ - chmod +x check-dependencies.sh && \ - chmod +x install-dependencies.sh && \ - chmod +x uninstall-dependencies.sh - ``` - - 2. Verify installed dependencies by running `check-dependencies.sh`: - - ``` - ./check-dependencies.sh - ``` - - > Note: Keep note of any missing dependencies. - - 3. Install dependencies by running `install-dependencies.sh`: - ``` - ./install-dependencies.sh - ``` - > Note: Install all missing dependencies and use check-dependencies script to ensure everything is installed and running. - 4. Uninstall dependencies by running `uninstall-dependencies.sh`: - - ``` - ./uninstall-dependencies.sh - ``` - - > Warning: Due to the destructive nature of the script (without further warnings), it should only be used during the initial setup of the dependencies. For example, Uninstalling PostgreSQL/Citus using script will lead to data loss. USE EXTREME CAUTION. - - > Warning: This script should only be used to uninstall dependencies that were installed via installation script in step 3. If same dependencies were installed using other methods, refrain from using this script. This script is provided in-order to reverse installation in-case issues arise from a bad install. - -- **MacOS** - - 1. Install Node.js 20: - - ``` - brew install node@20 - ``` - - ``` - brew link --overwrite node@20 - ``` - - 2. Install Kafka: - - ``` - brew install kafka - ``` - - > Note: To install Kafka on older macOS versions like Monterey (Intel architecture), you need to follow the manual installation process instead of using Homebrew. The process includes downloading Kafka, setting up ZooKeeper, and running Kafka services. You can find the official Kafka installation guide here: [Kafka Quickstart Guide](https://kafka.apache.org/quickstart).This ensures compatibility with older macOS systems. Follow the steps outlined in the documentation for a smooth setup. - - 3. Install PostgreSQL 16: - - ``` - brew install postgresql@16 - ``` - - 4. Install PM2: - - ``` - sudo npm install pm2@latest -g - ``` - - 5. Install Redis: - - ``` - brew install redis - ``` - - 6. Install mongDB: - - ``` - brew tap mongodb/brew - ``` - - ``` - brew install mongodb-community@4.4 - ``` - - ``` - brew link mongodb-community@4.4 --force - ``` - - ``` - brew services start mongodb-community@4.4 - ``` - - 7. Download `check-dependencies.sh` file: - - ``` - curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/native/scripts/macos/check-dependencies.sh && \ - chmod +x check-dependencies.sh - ``` - - 8. Verify installed dependencies by running `check-dependencies.sh`: - - ``` - ./check-dependencies.sh - ``` - - > Note : If you've manually installed Kafka without Homebrew, the script might incorrectly indicate that Kafka and Homebrew are not installed, as it checks only for Homebrew installations. In such cases, you can safely ignore this warning. Ensure that both Kafka and ZooKeeper are running on their default ports (ZooKeeper on `2181`, Kafka on `9092`). This will confirm proper installation and functionality despite the script's output. - -- **Windows** - - 1. Install Node.js 20: - - Download and install Node.js v20 for Windows platform (x64) from official [Node.js download page](https://nodejs.org/en/download). - - 2. Install Kafka 3.5.0: - - 1. Adapt the instructions given in the following ["Apache Kafka on Windows"](https://www.conduktor.io/kafka/how-to-install-apache-kafka-on-windows/) documentation to install Kafka version 3.5.0. - - > Note: As per the instructions, Kafka server and Zookeeper has to be kept active on different WSL terminals for the entire lifetime of ELEVATE-Project services. - - > Note: Multiple WSL terminals can be opened by launching `Ubuntu` from start menu. - - 2. Open a new WSL terminal and execute the following command to get the IP of the WSL instance. - - ``` - ip addr show eth0 - ``` - - Sample Output: - - ``` - 2: eth0: mtu 1492 qdisc mq state UP group default qlen 1000 - link/ether 11:56:54:f0:as:vf brd ff:ff:ff:ff:ff:ff - inet 172.12.46.150/20 brd 172.24.79.255 scope global eth0 - valid_lft forever preferred_lft forever - inet6 fe80::215:5dff:fee7:dc52/64 scope link - valid_lft forever preferred_lft forever - ``` - - Keep note of the IP address shown alongside `inet`. In the above case, `172.12.46.150` is IP address of the WSL instance. - - 3. In the same WSL terminal, navigate to `config` directory of Kafka from step 1 and make the following changes to `server.properties` file. - - - Uncomment `listeners=PLAINTEXT://:9092` line and change it to `listeners=PLAINTEXT://0.0.0.0:9092` to allow connections from any IP. - - - Uncomment `advertised.listeners` line and set it to `advertised.listeners=PLAINTEXT://172.12.46.150:9092`. Replace `172.12.46.150` with the actual IP address of your WSL instance. - - 4. Restart the Zookeeper and Kafka Server from their own WSL terminals from step 1. - - 3. Install Redis: - - 1. Follow the instructions given in the official [Redis Documentation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/) to install Redis using WSL. - - 2. Using the WSL terminal, open the Redis configuration file in a text editor, such as nano: - - ``` - sudo nano /etc/redis/redis.conf - ``` - - 3. Find the line containing `bind 127.0.0.1 ::1` and change it to `bind 0.0.0.0 ::.`. This change allows Redis to accept connections from any IP address. Then save and exit the file. - - 4. Restart Redis to apply the changes: - - ``` - sudo service redis-server restart - ``` - - 4. Install PM2: - - ``` - npm install pm2@latest -g - ``` - - 5. Install PostgreSQL 16: - - 1. Download and install PostgreSQL 16 from [EnterpriseDB PostgreSQL](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) download page. - - > Note: Set username and password for the default database to be 'postgres' during installation. - - 2. Once installed, Add `C:\Program Files\PostgreSQL\16\bin` to windows environment variables. Refer [here](https://www.computerhope.com/issues/ch000549.htm) or [here](https://stackoverflow.com/a/68851621) for more information regarding how to set it. - - 6. Install MongoDB: - - Follow the official [MongoDB Website](https://www.mongodb.com/try/download/community) to install MongoDB. - - 7. Install Gotenberg via Docker: - - 1. Download Docker Desktop for Windows from [Docker Website](https://docs.docker.com/desktop/setup/install/windows-install/) - - 2. Run the installer and follow the setup instructions. - - 3. Ensure Docker Desktop is running and configured to use Linux containers(default settings). - - 4. Open a terminal (e.g., Command Prompt). - - 5. Pull the Gotenberg image: - - ``` - docker pull gotenberg/gotenberg:latest - ``` - - 6. Run the Gotenberg container with the following command: - - ``` - docker run -d --name gotenberg -p 3000:3000 gotenberg/gotenberg:latest - ``` - - 7. Verify the container is running. You should see the Gotenberg container listed after running the below command. - ``` - docker ps - ``` - -## Installation - -1. **Create ELEVATE-Project Directory:** Create a directory named **ELEVATE-Project**. - - > Example Command: `mkdir ELEVATE-Project && cd ELEVATE-Project/` - -2. **Git Clone Services And Portal Repositories** - - - **Ubuntu/Linux/MacOS** - - ``` - git clone -b main https://github.com/ELEVATE-Project/project-service.git && \ - git clone -b main https://github.com/ELEVATE-Project/entity-management.git && \ - git clone -b master https://github.com/ELEVATE-Project/user.git && \ - git clone -b master https://github.com/ELEVATE-Project/notification.git && \ - git clone -b main https://github.com/ELEVATE-Project/interface-service.git && \ - git clone -b master https://github.com/ELEVATE-Project/scheduler.git && \ - git clone -b main https://github.com/ELEVATE-Project/observation-survey-projects-pwa - ``` - - - **Windows** - - ``` - git clone -b staging https://github.com/ELEVATE-Project/project-service.git & - git clone -b staging https://github.com/ELEVATE-Project/entity-management.git & - git clone -b master https://github.com/ELEVATE-Project/user.git & - git clone -b master https://github.com/ELEVATE-Project/notification.git & - git clone -b main https://github.com/ELEVATE-Project/interface-service.git & - git clone -b master https://github.com/ELEVATE-Project/scheduler.git & - git clone -b main https://github.com/ELEVATE-Project/observation-survey-projects-pwa - ``` - -3. **Install NPM Packages** - - - **Ubuntu/Linux/MacOS** - - ``` - cd project-service && npm install && cd ../ && \ - cd entity-management/src && npm install && cd ../.. && \ - cd user/src && npm install && cd ../.. && \ - cd notification/src && npm install && cd ../.. && \ - cd interface-service/src && npm install && cd ../.. && \ - cd scheduler/src && npm install && cd ../.. && \ - cd observation-survey-projects-pwa && npm install --force && cd .. - ``` - - - **Windows** - - ``` - cd project-service && npm install && cd .. - cd user\src && npm install && cd ..\.. - cd notification\src && npm install && cd ..\.. - cd interface-service\src && npm install && cd ..\.. - cd scheduler\src && npm install && cd ..\.. - cd observation-survey-projects-pwa && npm install --force && cd .. - ``` - - > Note: Entity-management service runs only on node-16 for Windows native setup. - - ``` - nvm use 16 - ``` - - ``` - cd entity-management\src && npm install && cd ..\.. - ``` - - > Note: Change the node version as it was before. - -4. **Download Environment Files** - - - **Ubuntu/Linux** - - ``` - curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env && \ - curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env && \ - curl -L -o user/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/user_env && \ - curl -L -o notification/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/notification_env && \ - curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env && \ - curl -L -o scheduler/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env && \ - curl -L -o observation-survey-projects-pwa/src/environments/environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts - ``` - - - **MacOs** - - ``` - curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env && \ - curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env && \ - curl -L -o user/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/non-citus/user_env && \ - curl -L -o notification/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/non-citus/notification_env && \ - curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env && \ - curl -L -o scheduler/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env && \ - curl -L -o observation-survey-projects-pwa/src/environments/environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts - ``` - - - **Windows** - - ``` - curl -L -o project-service\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env & - curl -L -o entity-management\src\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env & - curl -L -o user\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/user_env & - curl -L -o notification\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/notification_env & - curl -L -o interface-service\src\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env & - curl -L -o scheduler\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env & - curl -L -o observation-survey-projects-pwa\src\environments\environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts - ``` - - > **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-Management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. - - > **Caution:** While the default values in the downloaded environment files enable the ELEVATE-Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. - - > **Important:** As mentioned in the above linked document, the **User SignUp** functionality may be compromised if key environment variables are not set correctly during deployment. If you opt to skip this setup, consider using the sample user account generator detailed in the `Sample User Accounts Generation` section of this document. - -5. **Create Databases** - - - **Ubuntu/Linux** - - 1. Download `create-databases.sh` Script File: - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/create-databases.sh - ``` - - 2. Make the executable by running the following command: - ``` - chmod +x create-databases.sh - ``` - 3. Run the script file: - ``` - ./create-databases.sh - ``` - - - **MacOs** - - 1. Download `create-databases.sh` Script File: + ๐Ÿš€ Stand Alone Setup +
- ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/macos/create-databases.sh +This setup is ideal for **local development and testing**, where only the core Projects Service components are required. - ``` +In the **Stand-Alone Setup**, the **Samiksha service is not included**. This mode supports the complete lifecycle of **program creation and program consumption**, along with **project creation and project consumption**. Users can also **view and generate reports** based on the configured programs and projects. - 2. Make the executable by running the following command: - ``` - chmod +x create-databases.sh - ``` - 3. Run the script file: - ``` - ./create-databases.sh - ``` +This setup is recommended when survey and observation features powered by Samiksha are not required, and the focus is limited to core program and project management workflows. - - **Windows** - 1. Download `create-databases.bat` Script File: - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/windows/create-databases.bat - ``` - 2. Run the script file: - ``` - create-databases.bat - ``` +#### I. Docker Setup (Recommended) -6. **Run Migrations To Create Tables** +- [Setup guide for Linux](https://github.com/ELEVATE-Project/project-service/blob/main/documentation/3.4.0/setup/docker/stand-alone/ubuntu/README.md) +- [Setup guide for macOS](https://github.com/ELEVATE-Project/project-service/blob/main/documentation/3.4.0/setup/docker/stand-alone/mac-os/README.md) +- [Setup guide for Windows](https://github.com/ELEVATE-Project/project-service/blob/main/documentation/3.4.0/setup/docker/stand-alone/windows/README.md) - - **Ubuntu/Linux/MacOS** +
- 1. Run Migrations: - ``` - cd user/src && npx sequelize-cli db:migrate && cd ../.. && \ - cd notification/src && npx sequelize-cli db:migrate && cd ../.. - ``` +#### II. Native Setup (PM2 Managed Services) - - **Windows** - - 1. Run Migrations: - ``` - cd user\src && npx sequelize-cli db:migrate && cd ..\.. && cd notification\src && npx sequelize-cli db:migrate && cd ..\.. - ``` - -7. **Enabling Citus And Setting Distribution Columns (Optional)** - - To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. - - > NOTE: Currently only available for Linux based operation systems. - - 1. Download user `distributionColumns.sql` file. - - ``` - curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql - ``` - - 2. Set up the `citus_setup` file by following the steps given below. - - - **Ubuntu/Linux** - - 1. Download the `citus_setup.sh` file: - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/citus_setup.sh - - ``` - - 2. Make the setup file executable by running the following command: - - ``` - chmod +x citus_setup.sh - ``` - - 3. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. - ``` - ./citus_setup.sh user postgres://postgres:postgres@localhost:9700/users - ``` - -8. **Insert Initial Data** - - - **Ubuntu/Linux/MacOS** - - 1. Download `entity-project-sample-data.sh` Script File: - - 1.1. For ubuntu/linux - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/entity-project-sample-data.sh - ``` - - 1.1. For mac - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/macos/entity-project-sample-data.sh - ``` - - 2. Make the executable by running the following command: - ``` - chmod +x entity-project-sample-data.sh - ``` - 3. Run the script file: - ``` - ./entity-project-sample-data.sh - ``` - 4. Run seeders of user service - ``` - cd user/src && npm run db:seed:all && cd ../.. - ``` - - - **Windows** - - 1. Download `entity-project-sample-data.bat` Script File: - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/windows/entity-project-sample-data.bat - ``` - - 2. Run the script file: - - ``` - entity-project-sample-data.bat - ``` - - 3. Run seeders of user service - - ``` - cd user\src && npm run db:seed:all && cd ..\.. - ``` - -9. **Insert Forms Data into Database** - - - **Ubuntu/Linux/MacOS** - - 1. Download `import_forms.js` Script File And Make the setup file executable by running the following command: - - ``` - curl -s https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/import_forms.js | node - ``` - - - **Windows** - - 1. Download `import_forms_mongo.bat` Script File and execute the file by running the following commands: - - ``` - curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/windows/import_forms_mongo.bat - ``` - - ``` - import_forms_mongo.bat - ``` - -10. **Start The Services** - - Following the steps given below, 2 instances of each ELEVATE-Project backend service will be deployed and be managed by PM2 process manager. - - - **Ubuntu/Linux** - - ``` - (cd project-service && pm2 start app.js --name project-service && cd -) && \ - (cd entity-management/src && pm2 start app.js --name entity-management && cd -) && \ - (cd user/src && pm2 start app.js --name user && cd -) && \ - (cd notification/src && pm2 start app.js --name notification && cd -) && \ - (cd interface-service/src && pm2 start app.js --name interface && cd -) && \ - (cd scheduler/src && pm2 start app.js --name scheduler && cd -) - ``` - - - **MacOs** - - ``` - cd project-service && npx pm2 start app.js -i 2 --name project-service && cd .. && \ - cd entity-management/src && npx pm2 start app.js -i 2 --name entity-management && cd ../.. && \ - cd user/src && npx pm2 start app.js -i 2 --name user && cd ../.. && \ - cd notification/src && npx pm2 start app.js -i 2 --name notification && cd ../.. && \ - cd interface-service/src && npx pm2 start app.js -i 2 --name interface && cd ../.. && \ - cd scheduler/src && npx pm2 start app.js -i 2 --name scheduler && cd ../.. - ``` - - - **Windows** - - ``` - cd project-service && pm2 start app.js --name project-service && cd .. - cd entity-management\src && pm2 start app.js --name entity-management && cd ..\.. - cd user\src && pm2 start app.js --name user && cd ..\.. - cd notification\src && pm2 start app.js --name notification && cd ..\.. - cd interface-service\src && pm2 start app.js --name interface && cd ..\.. - cd scheduler\src && pm2 start app.js --name scheduler && cd ..\.. - ``` - -11. **Run Service Scripts** - - - **Ubuntu/Linux/MacOS** - - ``` - cd user/src/scripts && node insertDefaultOrg.js && node viewsScript.js && cd ../../.. - ``` - - - **Windows** - - ``` - cd user\src\scripts && node insertDefaultOrg.js && node viewsScript.js && cd ..\..\.. - ``` - -12. **Start The Portal** - - ELEVATE-Project portal utilizes Ionic for building the browser bundle, follow the steps given below to install them and start the portal. - - - **Ubuntu/Linux/Windows** - - 1. Install the Ionic framework: - - ``` - npm install -g ionic - ``` - - 2. Install the Ionic client: - - ``` - npm install -g @ionic/cli - ``` - - 3. Navigate to `observation-survey-projects-pwa` directory: - - ``` - cd observation-survey-projects-pwa - ``` - - 4. Run the project on your local system using the following command: - - ``` - ionic serve - ``` - - Navigate to http://localhost:8100 to access the ELEVATE-Project Portal. - -## Sample User Accounts Generation - -During the initial setup of ELEVATE-Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the ELEVATE-Project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. - -In such cases, you can generate sample user accounts using the steps below. This allows you to explore the ELEVATE-Project services and portal immediately after setup. - -> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. - -- **Ubuntu/Linux** - - ``` - curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/insert_sample_data.sh && \ - chmod +x insert_sample_data.sh && \ - ./insert_sample_data.sh - ``` - -- **MacOS** - - ``` - curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/macos/insert_sample_data.sh && \ - chmod +x insert_sample_data.sh && \ - ./insert_sample_data.sh - ``` - -- **Windows** - - ``` - curl -o insert_sample_data.bat https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/windows/insert_sample_data.bat && ^ - insert_sample_data.bat - ``` - -After successfully running the script mentioned above, the following user accounts will be created and available for login: - -| Email ID | Password | Role | -| ------------------------ | ---------- | ------------------------- | -| aaravpatel@example.com | Password1@ | State Educational Officer | -| arunimareddy@example.com | Password1@ | State Educational Officer | -| devikasingh@example.com | Password1@ | State Educational Officer | +- [Setup guide for Linux](https://github.com/ELEVATE-Project/project-service/blob/main/documentation/3.4.0/setup/native/stand-alone/ubuntu/README.md) +- [Setup guide for macOS](https://github.com/ELEVATE-Project/project-service/blob/main/documentation/3.4.0/setup/docker/stand-alone/mac-os/README.md) +- [Setup guide for Windows](link/to/standalone/native/windows/README)
-## Postman Collections - -- [Projects Service](https://github.com/ELEVATE-Project/project-service/tree/main/api-doc) - -## Adding New Projects to the System - -With implementation scripts, you can seamlessly add new projects to the system. Once a project is successfully added, it becomes visible on the portal, ready for use and interaction. For a comprehensive guide on setting up and using the implementation script, please refer to the [documentation here](https://github.com/ELEVATE-Project/project-service/tree/main/Project-Service-implementation-Script). - - - - +- **Legacy Version (1.0.0) Documentation** + + View 1.0.0 Documentation + -# Team +--- +## ๐Ÿ‘ฅ Team -# Open Source Dependencies - -Several open source dependencies that have aided Projects's development: +--- -![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) -![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) -![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) -![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) -![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +### Open Source Dependencies +This project uses several open-source tools and dependencies that supported its development - +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/document/resourceDelete/ReadME.md b/document/resourceDelete/ReadME.md index 24328dc3..9200896c 100644 --- a/document/resourceDelete/ReadME.md +++ b/document/resourceDelete/ReadME.md @@ -74,20 +74,62 @@ curl --location --request POST 'http://localhost:4301/project/v1/admin/deleteRes ```json { - "message": "Solution and associated resources deleted successfully", + "message": "Program and associated resources deleted successfull", "status": 200, "result": { - "deletedProgramsCount": 1, - "deletedSolutionsCount": 1, - "deletedProjectTemplatesCount": 2, - "deletedCertificateTemplatesCount": 1, - "deletedProjectTemplateTasksCount": 15, - "deletedSurveysCount": 0, - "deletedSurveySubmissionsCount": 0, - "deletedObservationsCount": 0, - "deletedObservationSubmissionsCount": 0, + "deletedPrograms": { + "deletedProgramsIds": ["695cb84c5dfcac0952f562f4"], + "deletedProgramsCount": 1 + }, + "deletedSolutions": { + "deletedSolutionsIds": [ + "695cb84f941a350e28bfa991", + "695cb857941a350e28bfaa03", + "695cb8645dfcac0952f56335", + "695cb8654f13df702d51c003", + "695cb8654f13df702d51c028" + ], + "deletedSolutionsCount": 5 + }, + "deletedProjectTemplates": { + "deletedProjectTemplatesIds": ["695cb8655dfcac0952f5633d"], + "deletedProjectTemplatesCount": 1 + }, + "deletedCertificateTemplates": { + "deletedCertificateTemplatesIds": ["695cb8655dfcac0952f56342", "695cb8655dfcac0952f56347"], + "deletedCertificateTemplatesCount": 2 + }, + "deletedProjectTemplateTasks": { + "deletedProjectTemplateTasksIds": [ + "695cb8655dfcac0952f56342", + "695cb8655dfcac0952f56347", + "695cb8655dfcac0952f5634c", + "695cb8655dfcac0952f56351", + "695cb8655dfcac0952f56355" + ], + "deletedProjectTemplateTasksCount": 5 + }, + "deletedSurveys": { + "deletedSurveysIds": ["695cb8655dfcac0952f56351", "695cb8655dfcac0952f56355"], + "deletedSurveysCount": 2 + }, + "deletedSurveySubmissions": { + "deletedSurveySubmissionsIds": ["695cb8655dfcac0952f56351", "695cb8655dfcac0952f56355"], + "deletedSurveySubmissionsCount": 2 + }, + "deletedObservations": { + "deletedObservationsIds": ["695cb84f941a350e28bfa991", "695cb857941a350e28bfaa03"], + "deletedObservationsCount": 2 + }, + "deletedObservationSubmissions": { + "deletedObservationSubmissionsIds": ["695cb84f941a350e28bfa991", "695cb857941a350e28bfaa03"], + "deletedObservationSubmissionsCount": 2 + }, "pullProgramFromUserExtensionCount": 0, - "deletedProjectsCount": 0 + "deletedProjects": { + "deletedProjectsIds": ["695cb8654f13df702d51c003", "695cb8654f13df702d51c028"], + "deletedProjectsCount": 2 + } } } ``` diff --git a/documentation/1.0.0/ReadMe.md b/documentation/1.0.0/ReadMe.md new file mode 100644 index 00000000..fddde5a5 --- /dev/null +++ b/documentation/1.0.0/ReadMe.md @@ -0,0 +1,1512 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Supported Operating Systems + +- **Ubuntu (Recommended: Version 20 and above)** +- **Windows (Recommended: Version 11 and above)** +- **macOs (Recommended: Version 12 and above)** + +# Setup Options + +**Project services can be setup using two methods:** + +> Note : This guide outlines two setup methods, detailed below. For a quick, beginner-friendly setup and walkthrough of services, it is recommended to use the Dockerized Services & Dependencies setup with the Docker-Compose file. + +
Dockerized Services & Dependencies Using Docker-Compose File + +## Dockerized Services & Dependencies + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Ubuntu users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Ubuntu](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04). To install and use Nodejs in Ubuntu machine, you can follow instructions here: [How To Install Nodejs in Ubuntu](https://nodejs.org/en/download/package-manager). For Windows and MacOS users, you can refer to the Docker documentation for installation instructions: [Docker Compose Installation Guide](https://docs.docker.com/compose/install/). Once these prerequisites are in place, you're all set to get started with setting up the Project application. + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Operating Systems: Linux / macOS + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for port in 3000 3001 3002 6000 5001 4000 9092 5432 7007 2181 2707 3569; do + if lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then + echo "Port $port is in use" + else + echo "Port $port is available" + fi +done +``` + +1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. + ` curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/mac-linux/setup_project.sh && chmod +x setup_project.sh && sudo ./setup_project.sh` + + > Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. + + **General Instructions :** + + 1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. + + 2. All docker containers can be stopped and removed by using below command. + ``` + sudo ./docker-compose-down.sh + ``` + 3. All services and dependencies can be started using below command. + ``` + sudo ./docker-compose-up.sh + ``` + + **Keep the current terminal session active, and kindly open a new terminal window within the project directory.** + +**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** + +## Operating Systems: Windows + +1. **Download Docker Compose File:** Retrieve the **[docker-compose-project.yml](https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml)** file from the Project service repository and save it to the project directory. + + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml + ``` + + > Note: All commands are run from the project directory. + +2. **Download Environment Files**: Using the OS specific commands given below, download environment files for all the services. + + - **Windows** + + ``` + curl -L ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/interface_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/entity_management_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/project_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/notification_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/scheduler_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/user_env ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/envs/env.js + ``` + + > **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + + > **Caution:** While the default values in the downloaded environment files enable the Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + +3. **Download `replace_volume_path` Script File** + + - **Windows** + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/dockerized/scripts/windows/replace_volume_path.bat + ``` + +4. **Run `replace_volume_path` Script File** + + - **Windows** + + Run the script file either by double clicking it or by executing the following command from the terminal. + + ``` + replace_volume_path.bat + ``` + + > **Note**: The provided script file replaces the host path for the **portal** service container volume in the `docker-compose-project.yml` file with your current directory path. + > + > volumes: + > + > \- /home/shikshalokam/elevate/single-click/linux/env.js:/usr/src/app/www/assets/env/env.js + +5. **Download `docker-compose-up` & `docker-compose-down` Script Files** + + - **Windows** + + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/docker-compose-up.bat + ``` + + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/docker-compose-down.bat + ``` + +6. **Run All Services & Dependencies**:All services and dependencies can be started using the `docker-compose-up` script file. + + - **Windows** + + ``` + docker-compose-up.bat + ``` + + > Double-click the file or run the above command from the terminal. + + > **Note**: During the first Docker Compose run, the database, migration seeder files, and the script to set the default organization will be executed automatically. + +7. **Remove All Service & Dependency Containers**: + All docker containers can be stopped and removed by using the `docker-compose-down` file. + + - **Windows** + + ``` + docker-compose-down.bat + ``` + + > **Caution**: As per the default configuration in the `docker-compose-project.yml` file, using the `down` command will lead to data loss since the database container does not persist data. To persist data across `down` commands and subsequent container removals, refer to the "Persistence of Database Data in Docker Containers" section of this documentation. + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. (Skip this for linux/macOs) + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` +2. Set up the citus_setup file by following the steps given below. + + - **Ubuntu/Linux/Mac** + + 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + ``` + sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + + - **Windows** + 1. Download the `citus_setup.bat` file. + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/citus_setup.bat + ``` + 2. Enable Citus and set distribution columns for `user` database by running the `citus_setup.bat`with the following arguments. + ``` + citus_setup.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + > **Note:** Since the `citus_setup.bat` file requires arguments, it must be run from a terminal. + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +- **Ubuntu/Linux/Mac** + + ``` + sudo ./insert_sample_data.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + +- **Windows** + + 1. **Download The `sampleData.sql` Files:** + + ``` + mkdir sample-data\user 2>nul & ^ + curl -L "https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/sample-data/windows/user/sampleData.sql" -o sample-data\user\sampleData.sql + ``` + + 2. **Download The `insert_sample_data` Script File:** + + ``` + curl -L -o insert_sample_data.bat https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/dockerized/scripts/windows/insert_sample_data.bat + ``` + + 3. **Run The `insert_sample_data` Script File:** + + ``` + insert_sample_data.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + + After successfully running the script mentioned above, the following user accounts will be created and available for login: + + | Email ID | Password | Role | + | ------------------------ | ---------- | ----------------------- | + | aaravpatel@example.com | Password1@ | State Education Officer | + | arunimareddy@example.com | Password1@ | State Education Officer | + | devikasingh@example.com | Password1@ | State Education Officer | + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + - **Ubuntu/Linux/Mac** + + 1. Insert sample data by running the following command. + + ``` + sudo ./add_sample_project_entity_data.sh + ``` + + - **Windows** + + 1. Download `entity-project-sample-data.bat` Script File: + + ``` + curl -L ^ + -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/entity-project-sample-data.bat ^ + ``` + + 2. Make the setup file executable by running the following command. + + ``` + entity-project-sample-data.bat + ``` + +## Default Forms Creation for Portal Configuration + +This step inserts configuration forms into MongoDB, enabling or disabling features and fields on portal pages. + +#### Insert Forms Data into Database + +- **Ubuntu/Linux/Mac**: + + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/mac-linux/import_forms_mongo.sh && chmod +x import_forms_mongo.sh && sudo ./import_forms_mongo.sh mongodb://mongo:27017/elevate-project + ``` + +- **Windows**: + 1. Download the `import_forms_mongo.bat` file: + ```cmd + curl -L -O https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/import_forms_mongo.bat + ``` + 2. Run the script: + ```cmd + import_forms_mongo.bat mongodb://localhost:27017/elevate-project + ``` + +## Explore the Portal + +Once the services are up and the front-end app bundle is built successfully, navigate to **[localhost:7007](http://localhost:7007/)** to access the Project app. + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +
+ +
+Natively Installed Services & Dependencies + +## PM2 Managed Services & Natively Installed Dependencies + +### System Requirements + +- **Node.jsยฎ:** v20 +- **PostgreSQL:** 16 +- **Apache Kafkaยฎ:** 3.5.0 +- **MongoDB:** 4.4.14 +- **Gotenberg:** 8.5.0 + +Expectation: Upon following the prescribed steps, you will achieve a fully operational ELEVATE-Project application setup. Both the portal and backend services are managed using PM2, with all dependencies installed natively on the host system. + +## Prerequisites + +Before setting up the following ELEVATE-Project application, dependencies given below should be installed and verified to be running. Refer to the steps given below to install them and verify. + +- **Ubuntu/Linux** + + 1. Download dependency management scripts: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/check-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/install-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/uninstall-dependencies.sh && \ + chmod +x check-dependencies.sh && \ + chmod +x install-dependencies.sh && \ + chmod +x uninstall-dependencies.sh + ``` + + 2. Verify installed dependencies by running `check-dependencies.sh`: + + ``` + ./check-dependencies.sh + ``` + + > Note: Keep note of any missing dependencies. + + 3. Install dependencies by running `install-dependencies.sh`: + ``` + ./install-dependencies.sh + ``` + > Note: Install all missing dependencies and use check-dependencies script to ensure everything is installed and running. + 4. Uninstall dependencies by running `uninstall-dependencies.sh`: + + ``` + ./uninstall-dependencies.sh + ``` + + > Warning: Due to the destructive nature of the script (without further warnings), it should only be used during the initial setup of the dependencies. For example, Uninstalling PostgreSQL/Citus using script will lead to data loss. USE EXTREME CAUTION. + + > Warning: This script should only be used to uninstall dependencies that were installed via installation script in step 3. If same dependencies were installed using other methods, refrain from using this script. This script is provided in-order to reverse installation in-case issues arise from a bad install. + +- **MacOS** + + 1. Install Node.js 20: + + ``` + brew install node@20 + ``` + + ``` + brew link --overwrite node@20 + ``` + + 2. Install Kafka: + + ``` + brew install kafka + ``` + + > Note: To install Kafka on older macOS versions like Monterey (Intel architecture), you need to follow the manual installation process instead of using Homebrew. The process includes downloading Kafka, setting up ZooKeeper, and running Kafka services. You can find the official Kafka installation guide here: [Kafka Quickstart Guide](https://kafka.apache.org/quickstart).This ensures compatibility with older macOS systems. Follow the steps outlined in the documentation for a smooth setup. + + 3. Install PostgreSQL 16: + + ``` + brew install postgresql@16 + ``` + + 4. Install PM2: + + ``` + sudo npm install pm2@latest -g + ``` + + 5. Install Redis: + + ``` + brew install redis + ``` + + 6. Install mongDB: + + ``` + brew tap mongodb/brew + ``` + + ``` + brew install mongodb-community@4.4 + ``` + + ``` + brew link mongodb-community@4.4 --force + ``` + + ``` + brew services start mongodb-community@4.4 + ``` + + 7. Download `check-dependencies.sh` file: + + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/native/scripts/macos/check-dependencies.sh && \ + chmod +x check-dependencies.sh + ``` + + 8. Verify installed dependencies by running `check-dependencies.sh`: + + ``` + ./check-dependencies.sh + ``` + + > Note : If you've manually installed Kafka without Homebrew, the script might incorrectly indicate that Kafka and Homebrew are not installed, as it checks only for Homebrew installations. In such cases, you can safely ignore this warning. Ensure that both Kafka and ZooKeeper are running on their default ports (ZooKeeper on `2181`, Kafka on `9092`). This will confirm proper installation and functionality despite the script's output. + +- **Windows** + + 1. Install Node.js 20: + + Download and install Node.js v20 for Windows platform (x64) from official [Node.js download page](https://nodejs.org/en/download). + + 2. Install Kafka 3.5.0: + + 1. Adapt the instructions given in the following ["Apache Kafka on Windows"](https://www.conduktor.io/kafka/how-to-install-apache-kafka-on-windows/) documentation to install Kafka version 3.5.0. + + > Note: As per the instructions, Kafka server and Zookeeper has to be kept active on different WSL terminals for the entire lifetime of ELEVATE-Project services. + + > Note: Multiple WSL terminals can be opened by launching `Ubuntu` from start menu. + + 2. Open a new WSL terminal and execute the following command to get the IP of the WSL instance. + + ``` + ip addr show eth0 + ``` + + Sample Output: + + ``` + 2: eth0: mtu 1492 qdisc mq state UP group default qlen 1000 + link/ether 11:56:54:f0:as:vf brd ff:ff:ff:ff:ff:ff + inet 172.12.46.150/20 brd 172.24.79.255 scope global eth0 + valid_lft forever preferred_lft forever + inet6 fe80::215:5dff:fee7:dc52/64 scope link + valid_lft forever preferred_lft forever + ``` + + Keep note of the IP address shown alongside `inet`. In the above case, `172.12.46.150` is IP address of the WSL instance. + + 3. In the same WSL terminal, navigate to `config` directory of Kafka from step 1 and make the following changes to `server.properties` file. + + - Uncomment `listeners=PLAINTEXT://:9092` line and change it to `listeners=PLAINTEXT://0.0.0.0:9092` to allow connections from any IP. + + - Uncomment `advertised.listeners` line and set it to `advertised.listeners=PLAINTEXT://172.12.46.150:9092`. Replace `172.12.46.150` with the actual IP address of your WSL instance. + + 4. Restart the Zookeeper and Kafka Server from their own WSL terminals from step 1. + + 3. Install Redis: + + 1. Follow the instructions given in the official [Redis Documentation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/) to install Redis using WSL. + + 2. Using the WSL terminal, open the Redis configuration file in a text editor, such as nano: + + ``` + sudo nano /etc/redis/redis.conf + ``` + + 3. Find the line containing `bind 127.0.0.1 ::1` and change it to `bind 0.0.0.0 ::.`. This change allows Redis to accept connections from any IP address. Then save and exit the file. + + 4. Restart Redis to apply the changes: + + ``` + sudo service redis-server restart + ``` + + 4. Install PM2: + + ``` + npm install pm2@latest -g + ``` + + 5. Install PostgreSQL 16: + + 1. Download and install PostgreSQL 16 from [EnterpriseDB PostgreSQL](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) download page. + + > Note: Set username and password for the default database to be 'postgres' during installation. + + 2. Once installed, Add `C:\Program Files\PostgreSQL\16\bin` to windows environment variables. Refer [here](https://www.computerhope.com/issues/ch000549.htm) or [here](https://stackoverflow.com/a/68851621) for more information regarding how to set it. + + 6. Install MongoDB: + + Follow the official [MongoDB Website](https://www.mongodb.com/try/download/community) to install MongoDB. + + 7. Install Gotenberg via Docker: + + 1. Download Docker Desktop for Windows from [Docker Website](https://docs.docker.com/desktop/setup/install/windows-install/) + + 2. Run the installer and follow the setup instructions. + + 3. Ensure Docker Desktop is running and configured to use Linux containers(default settings). + + 4. Open a terminal (e.g., Command Prompt). + + 5. Pull the Gotenberg image: + + ``` + docker pull gotenberg/gotenberg:latest + ``` + + 6. Run the Gotenberg container with the following command: + + ``` + docker run -d --name gotenberg -p 3000:3000 gotenberg/gotenberg:latest + ``` + + 7. Verify the container is running. You should see the Gotenberg container listed after running the below command. + ``` + docker ps + ``` + +## Installation + +1. **Create ELEVATE-Project Directory:** Create a directory named **ELEVATE-Project**. + + > Example Command: `mkdir ELEVATE-Project && cd ELEVATE-Project/` + +2. **Git Clone Services And Portal Repositories** + + - **Ubuntu/Linux/MacOS** + + ``` + git clone -b main https://github.com/ELEVATE-Project/project-service.git && \ + git clone -b main https://github.com/ELEVATE-Project/entity-management.git && \ + git clone -b master https://github.com/ELEVATE-Project/user.git && \ + git clone -b master https://github.com/ELEVATE-Project/notification.git && \ + git clone -b main https://github.com/ELEVATE-Project/interface-service.git && \ + git clone -b master https://github.com/ELEVATE-Project/scheduler.git && \ + git clone -b main https://github.com/ELEVATE-Project/observation-survey-projects-pwa + ``` + + - **Windows** + + ``` + git clone -b staging https://github.com/ELEVATE-Project/project-service.git & + git clone -b staging https://github.com/ELEVATE-Project/entity-management.git & + git clone -b master https://github.com/ELEVATE-Project/user.git & + git clone -b master https://github.com/ELEVATE-Project/notification.git & + git clone -b main https://github.com/ELEVATE-Project/interface-service.git & + git clone -b master https://github.com/ELEVATE-Project/scheduler.git & + git clone -b main https://github.com/ELEVATE-Project/observation-survey-projects-pwa + ``` + +3. **Install NPM Packages** + + - **Ubuntu/Linux/MacOS** + + ``` + cd project-service && npm install && cd ../ && \ + cd entity-management/src && npm install && cd ../.. && \ + cd user/src && npm install && cd ../.. && \ + cd notification/src && npm install && cd ../.. && \ + cd interface-service/src && npm install && cd ../.. && \ + cd scheduler/src && npm install && cd ../.. && \ + cd observation-survey-projects-pwa && npm install --force && cd .. + ``` + + - **Windows** + + ``` + cd project-service && npm install && cd .. + cd user\src && npm install && cd ..\.. + cd notification\src && npm install && cd ..\.. + cd interface-service\src && npm install && cd ..\.. + cd scheduler\src && npm install && cd ..\.. + cd observation-survey-projects-pwa && npm install --force && cd .. + ``` + + > Note: Entity-management service runs only on node-16 for Windows native setup. + + ``` + nvm use 16 + ``` + + ``` + cd entity-management\src && npm install && cd ..\.. + ``` + + > Note: Change the node version as it was before. + +4. **Download Environment Files** + + - **Ubuntu/Linux** + + ``` + curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env && \ + curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env && \ + curl -L -o user/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/user_env && \ + curl -L -o notification/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/notification_env && \ + curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env && \ + curl -L -o scheduler/src/.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env && \ + curl -L -o observation-survey-projects-pwa/src/environments/environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts + ``` + + - **MacOs** + + ``` + curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env && \ + curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env && \ + curl -L -o user/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/non-citus/user_env && \ + curl -L -o notification/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/non-citus/notification_env && \ + curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env && \ + curl -L -o scheduler/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env && \ + curl -L -o observation-survey-projects-pwa/src/environments/environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts + ``` + + - **Windows** + + ``` + curl -L -o project-service\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/project_env & + curl -L -o entity-management\src\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/entity_management_env & + curl -L -o user\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/user_env & + curl -L -o notification\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/notification_env & + curl -L -o interface-service\src\.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/interface_env & + curl -L -o scheduler\src\.env https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/native/envs/scheduler_env & + curl -L -o observation-survey-projects-pwa\src\environments\environment.ts https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/envs/enviroment.ts + ``` + + > **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-Management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + + > **Caution:** While the default values in the downloaded environment files enable the ELEVATE-Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + + > **Important:** As mentioned in the above linked document, the **User SignUp** functionality may be compromised if key environment variables are not set correctly during deployment. If you opt to skip this setup, consider using the sample user account generator detailed in the `Sample User Accounts Generation` section of this document. + +5. **Create Databases** + + - **Ubuntu/Linux** + + 1. Download `create-databases.sh` Script File: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/create-databases.sh + ``` + + 2. Make the executable by running the following command: + ``` + chmod +x create-databases.sh + ``` + 3. Run the script file: + ``` + ./create-databases.sh + ``` + + - **MacOs** + + 1. Download `create-databases.sh` Script File: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/macos/create-databases.sh + + ``` + + 2. Make the executable by running the following command: + ``` + chmod +x create-databases.sh + ``` + 3. Run the script file: + ``` + ./create-databases.sh + ``` + + - **Windows** + + 1. Download `create-databases.bat` Script File: + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/windows/create-databases.bat + ``` + 2. Run the script file: + ``` + create-databases.bat + ``` + +6. **Run Migrations To Create Tables** + + - **Ubuntu/Linux/MacOS** + + 1. Run Migrations: + ``` + cd user/src && npx sequelize-cli db:migrate && cd ../.. && \ + cd notification/src && npx sequelize-cli db:migrate && cd ../.. + ``` + + - **Windows** + + 1. Run Migrations: + ``` + cd user\src && npx sequelize-cli db:migrate && cd ..\.. && cd notification\src && npx sequelize-cli db:migrate && cd ..\.. + ``` + +7. **Enabling Citus And Setting Distribution Columns (Optional)** + + To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + + > NOTE: Currently only available for Linux based operation systems. + + 1. Download user `distributionColumns.sql` file. + + ``` + curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/refs/heads/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` + + 2. Set up the `citus_setup` file by following the steps given below. + + - **Ubuntu/Linux** + + 1. Download the `citus_setup.sh` file: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/citus_setup.sh + + ``` + + 2. Make the setup file executable by running the following command: + + ``` + chmod +x citus_setup.sh + ``` + + 3. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + ``` + ./citus_setup.sh user postgres://postgres:postgres@localhost:9700/users + ``` + +8. **Insert Initial Data** + + - **Ubuntu/Linux/MacOS** + + 1. Download `entity-project-sample-data.sh` Script File: + + 1.1. For ubuntu/linux + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/entity-project-sample-data.sh + ``` + + 1.1. For mac + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/macos/entity-project-sample-data.sh + ``` + + 2. Make the executable by running the following command: + ``` + chmod +x entity-project-sample-data.sh + ``` + 3. Run the script file: + ``` + ./entity-project-sample-data.sh + ``` + 4. Run seeders of user service + ``` + cd user/src && npm run db:seed:all && cd ../.. + ``` + + - **Windows** + + 1. Download `entity-project-sample-data.bat` Script File: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/windows/entity-project-sample-data.bat + ``` + + 2. Run the script file: + + ``` + entity-project-sample-data.bat + ``` + + 3. Run seeders of user service + + ``` + cd user\src && npm run db:seed:all && cd ..\.. + ``` + +9. **Insert Forms Data into Database** + + - **Ubuntu/Linux/MacOS** + + 1. Download `import_forms.js` Script File And Make the setup file executable by running the following command: + + ``` + curl -s https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/import_forms.js | node + ``` + + - **Windows** + + 1. Download `import_forms_mongo.bat` Script File and execute the file by running the following commands: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/windows/import_forms_mongo.bat + ``` + + ``` + import_forms_mongo.bat + ``` + +10. **Start The Services** + + Following the steps given below, 2 instances of each ELEVATE-Project backend service will be deployed and be managed by PM2 process manager. + + - **Ubuntu/Linux** + + ``` + (cd project-service && pm2 start app.js --name project-service && cd -) && \ + (cd entity-management/src && pm2 start app.js --name entity-management && cd -) && \ + (cd user/src && pm2 start app.js --name user && cd -) && \ + (cd notification/src && pm2 start app.js --name notification && cd -) && \ + (cd interface-service/src && pm2 start app.js --name interface && cd -) && \ + (cd scheduler/src && pm2 start app.js --name scheduler && cd -) + ``` + + - **MacOs** + + ``` + cd project-service && npx pm2 start app.js -i 2 --name project-service && cd .. && \ + cd entity-management/src && npx pm2 start app.js -i 2 --name entity-management && cd ../.. && \ + cd user/src && npx pm2 start app.js -i 2 --name user && cd ../.. && \ + cd notification/src && npx pm2 start app.js -i 2 --name notification && cd ../.. && \ + cd interface-service/src && npx pm2 start app.js -i 2 --name interface && cd ../.. && \ + cd scheduler/src && npx pm2 start app.js -i 2 --name scheduler && cd ../.. + ``` + + - **Windows** + + ``` + cd project-service && pm2 start app.js --name project-service && cd .. + cd entity-management\src && pm2 start app.js --name entity-management && cd ..\.. + cd user\src && pm2 start app.js --name user && cd ..\.. + cd notification\src && pm2 start app.js --name notification && cd ..\.. + cd interface-service\src && pm2 start app.js --name interface && cd ..\.. + cd scheduler\src && pm2 start app.js --name scheduler && cd ..\.. + ``` + +11. **Run Service Scripts** + + - **Ubuntu/Linux/MacOS** + + ``` + cd user/src/scripts && node insertDefaultOrg.js && node viewsScript.js && cd ../../.. + ``` + + - **Windows** + + ``` + cd user\src\scripts && node insertDefaultOrg.js && node viewsScript.js && cd ..\..\.. + ``` + +12. **Start The Portal** + + ELEVATE-Project portal utilizes Ionic for building the browser bundle, follow the steps given below to install them and start the portal. + + - **Ubuntu/Linux/Windows** + + 1. Install the Ionic framework: + + ``` + npm install -g ionic + ``` + + 2. Install the Ionic client: + + ``` + npm install -g @ionic/cli + ``` + + 3. Navigate to `observation-survey-projects-pwa` directory: + + ``` + cd observation-survey-projects-pwa + ``` + + 4. Run the project on your local system using the following command: + + ``` + ionic serve + ``` + + Navigate to http://localhost:8100 to access the ELEVATE-Project Portal. + +## Sample User Accounts Generation + +During the initial setup of ELEVATE-Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the ELEVATE-Project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the ELEVATE-Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +- **Ubuntu/Linux** + + ``` + curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/linux/insert_sample_data.sh && \ + chmod +x insert_sample_data.sh && \ + ./insert_sample_data.sh + ``` + +- **MacOS** + + ``` + curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/macos/insert_sample_data.sh && \ + chmod +x insert_sample_data.sh && \ + ./insert_sample_data.sh + ``` + +- **Windows** + + ``` + curl -o insert_sample_data.bat https://raw.githubusercontent.com/ELEVATE-Project/project-service/main/documentation/1.0.0/native/scripts/windows/insert_sample_data.bat && ^ + insert_sample_data.bat + ``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ------------------------ | ---------- | ------------------------- | +| aaravpatel@example.com | Password1@ | State Educational Officer | +| arunimareddy@example.com | Password1@ | State Educational Officer | +| devikasingh@example.com | Password1@ | State Educational Officer | + +
+ +## Postman Collections + +- [Projects Service](https://github.com/ELEVATE-Project/project-service/tree/main/api-doc) + +## Adding New Projects to the System + +With implementation scripts, you can seamlessly add new projects to the system. Once a project is successfully added, it becomes visible on the portal, ready for use and interaction. For a comprehensive guide on setting up and using the implementation script, please refer to the [documentation here](https://github.com/ELEVATE-Project/project-service/tree/main/Project-Service-implementation-Script). + + + + + +# Team + + + + + +# Open Source Dependencies + +Several open source dependencies that have aided Projects's development: + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Jest](https://img.shields.io/badge/-jest-%23C21325?style=for-the-badge&logo=jest&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) + + diff --git a/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js b/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js new file mode 100644 index 00000000..b0b3e335 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js @@ -0,0 +1,290 @@ +const { ObjectId } = require('mongodb') + +let entityType = [ + { + _id: new ObjectId('6825914b97b5680013e6a140'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'state', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:31.680Z'), + createdAt: new Date('2025-05-15T07:01:31.680Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('6825915197b5680013e6a142'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'district', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:37.892Z'), + createdAt: new Date('2025-05-15T07:01:37.892Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591cc97b5680013e6a15c'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'professional_role', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:40.376Z'), + createdAt: new Date('2025-05-15T07:03:40.376Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591d397b5680013e6a15e'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'professional_subroles', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:47.062Z'), + createdAt: new Date('2025-05-15T07:03:47.062Z'), + __v: 0, + orgId: 'default_code', + }, +] + +let entities = [ + { + _id: new ObjectId('6852c86c7248c20014b38a4d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16', + name: 'Tripura', + }, + childHierarchyPath: ['district', 'block', 'cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825914b97b5680013e6a140'), + entityType: 'state', + registryDetails: { + code: '16', + locationId: '16', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:29:00.266Z'), + createdAt: new Date('2025-06-18T14:08:44.438Z'), + __v: 0, + groups: { + district: [new ObjectId('6852c8ae7248c20014b38a57')], + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8ae7248c20014b38a57'), + metaInformation: { + targetedEntityTypes: [], + externalId: 'westTripura', + name: 'West Tripura', + }, + childHierarchyPath: ['block', 'cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915197b5680013e6a142'), + entityType: 'district', + registryDetails: { + code: 'westTripura', + locationId: 'westTripura', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:27:43.218Z'), + createdAt: new Date('2025-06-18T14:09:50.337Z'), + __v: 0, + groups: { + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8de7248c20014b38a9d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '160101', + name: 'AGARTALA MUNICIPAL COORPORATION', + }, + childHierarchyPath: ['cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915597b5680013e6a144'), + entityType: 'block', + registryDetails: { + code: '160101', + locationId: '160101', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:24:30.469Z'), + createdAt: new Date('2025-06-18T14:10:38.736Z'), + __v: 0, + groups: { + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9027248c20014b38c34'), + metaInformation: { + targetedEntityTypes: [], + externalId: '1601010004', + name: 'ACHARYA PRAFULLA CHANDRA H/S SCHOOL', + }, + childHierarchyPath: ['school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915897b5680013e6a146'), + entityType: 'cluster', + registryDetails: { + code: '1601010004', + locationId: '1601010004', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:22:16.044Z'), + createdAt: new Date('2025-06-18T14:11:14.746Z'), + __v: 0, + groups: { + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9237248c20014b39fa0'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16010100422', + name: 'ABINASH GOPE SMRITI (SAROJANI) JB SCHOOL', + }, + childHierarchyPath: [], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915c97b5680013e6a148'), + entityType: 'school', + registryDetails: { + code: '16010100422', + locationId: '16010100422', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:11:49.194Z'), + createdAt: new Date('2025-06-18T14:11:49.194Z'), + __v: 0, + }, + { + _id: new ObjectId('68876746b19aea00144c2af9'), + metaInformation: { + targetedEntityTypes: [ + { + entityTypeId: '6825915197b5680013e6a142', + entityType: 'district', + }, + ], + externalId: 'Facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_role', 'professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591cc97b5680013e6a15c'), + entityType: 'professional_role', + registryDetails: { + locationId: 'Facilitator', + code: 'Facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-28T12:08:56.065Z'), + createdAt: new Date('2025-07-28T12:04:22.011Z'), + __v: 0, + groups: { + professional_subroles: [new ObjectId('688767deb19aea00144c2b08')], + }, + }, + { + _id: new ObjectId('688767deb19aea00144c2b08'), + metaInformation: { + targetedEntityTypes: [ + { + entityType: 'Handbook1_Activity', + entityTypeId: '688762feb19aea00144c2a81', + }, + { + entityType: 'Handbook2_Activity', + entityTypeId: '68887766b19aea00144c3631', + }, + ], + externalId: 'facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591d397b5680013e6a15e'), + entityType: 'professional_subroles', + registryDetails: { + locationId: 'facilitator', + code: 'facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-29T07:28:05.355Z'), + createdAt: new Date('2025-07-28T12:06:54.072Z'), + __v: 0, + }, +] + +module.exports = { + entities, + entityType, +} \ No newline at end of file diff --git a/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js b/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js new file mode 100644 index 00000000..6b02bb98 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js @@ -0,0 +1,192 @@ +const { MongoClient } = require('mongodb') + +const url = 'mongodb://localhost:27017/' // MongoDB URL +const projectDB = 'elevate-project' +const entityDB = 'elevate-entity' +const samikshaDB = "elevate-samiksha"; +const entityData = require('./entity_sampleData.js') +const projectData = require('./project_sampleData.js') +const surveyData = require("./survey_sampleData.js"); + +// MongoDB Error Code for Duplicate Key +const DUPLICATE_KEY_ERROR_CODE = 11000 + +// --- UTILITY FUNCTIONS --- + +/** + * Drops the specified collection, effectively deleting all data. + * @param {string} collectionName The name of the collection to drop. + * @param {string} currentDB The name of the database. + */ +async function cleanData(collectionName, currentDB) { + const client = new MongoClient(url) + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const exists = await collection.findOne({}) + if (exists) { + await collection.drop() + console.log(`๐Ÿ—‘๏ธ Successfully dropped collection: ${currentDB}.${collectionName}`) + } else { + // Use .listCollections for a more definitive check if needed, but drop() is usually safe. + console.log(`โ„น๏ธ Collection ${collectionName} in ${currentDB} does not exist or is empty. Skipping drop.`) + } + } catch (error) { + // This catches general connection or other drop errors + console.error(`โŒ Error dropping collection ${collectionName} in ${currentDB}: ${error.message}`) + } finally { + await client.close() + } +} + +/** + * Inserts data into the specified collection and provides detailed status messages. + * (This function is kept the same as your previous version for insertion logic) + * @param {string} collectionName The name of the collection. + * @param {Array} dataFile The array of documents to insert. + * @param {string} currentDB The name of the database. + */ +async function insertData(collectionName, dataFile, currentDB = projectDB) { + const client = new MongoClient(url) + + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const data = dataFile + + if (!data || data.length === 0) { + return + } + + console.log(`\n--- Attempting insertion into: ${currentDB}.${collectionName} ---`) + + const results = [] + await Promise.all( + data.map(async (doc, index) => { + const tempId = doc._id || `(Document Index: ${index})` + + try { + const result = await collection.insertOne(doc) + const finalId = result.insertedId || doc._id + + results.push({ + id: finalId, + status: 'SUCCESS', + message: `Document successfully created with _id: ${finalId}`, + }) + } catch (error) { + if (error.code === DUPLICATE_KEY_ERROR_CODE) { + results.push({ + id: tempId, + status: 'DUPLICATE', + message: `The data with identifier ${tempId} is already present in the DB. Please ensure unique identifiers are provided or clean the existing data.`, + }) + } else { + // Catch other errors (e.g., validation failure, connection issues) + results.push({ + id: tempId, + status: 'FAILURE', + message: `Error inserting document ${tempId}: ${error.message}`, + }) + } + } + }) + ) + + // Print the detailed results + results.forEach((res) => { + let message = '' + if (res.status === 'SUCCESS') { + message = `โœ… SUCCESS: ${res.message}` + } else if (res.status === 'DUPLICATE') { + message = `โš ๏ธ DUPLICATE: ${res.message}` + } else { + message = `โŒ FAILURE: ${res.message}` + } + console.log(message) + }) + } catch (globalError) { + console.error(`\nFatal error connecting to or operating on the database: ${globalError.message}`) + } finally { + await client.close() + } +} + + +async function main({ dataToBeInserted }) { + const collectionsToInsert = [ + { name: 'entities', data: dataToBeInserted.entities, db: entityDB }, + { name: 'entityTypes', data: dataToBeInserted.entityType, db: entityDB }, + { name: 'programs', data: dataToBeInserted.programData, db: projectDB }, + { name: 'solutions', data: dataToBeInserted.solutionData, db: projectDB }, + { name: 'projectTemplates', data: dataToBeInserted.projectTemplatesData, db: projectDB }, + { name: 'projectTemplateTasks', data: dataToBeInserted.projectTemplateTasksData, db: projectDB }, + { name: 'certificateTemplates', data: dataToBeInserted.certificateTemplatesData, db: projectDB }, + { name: 'certificateBaseTemplates', data: dataToBeInserted.certificateBaseTemplatesData, db: projectDB }, + { name: 'projectCategories', data: dataToBeInserted.projectCategoriesData, db: projectDB }, + { name: 'configurations', data: dataToBeInserted.configurationData, db: projectDB }, + { name: 'organizationExtension', data: dataToBeInserted.organizationExtensionData, db: projectDB }, + { name: "solutions", data: dataToBeInserted.solutionData, db:samikshaDB}, + { name: "criteria", data:dataToBeInserted.criteriaData, db : samikshaDB}, + { name: "criteriaQuestions", data: dataToBeInserted.criteriaQuestionsData, db : samikshaDB}, + { name: "frameworks", data: dataToBeInserted.frameworkData, db : samikshaDB}, + { name: "questions", data: dataToBeInserted.questionsData, db : samikshaDB}, + { name: "observations", data: dataToBeInserted.observationData, db : samikshaDB}, + { name: "surveys", data: dataToBeInserted.surveyData, db : samikshaDB}, + { name: "organizationExtension", data: dataToBeInserted.organizationExtensionData, db : samikshaDB}, + + ] + + console.log(`\n=================================================`) + console.log( + `๐Ÿ—‘๏ธ Starting CLEANUP for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data & Survey Data' } Collections...` + ) + console.log(`=================================================`) + + for (const item of collectionsToInsert) { + if (item.data) { + await cleanData(item.name, item.db) + } + } + + console.log(`\n=================================================`) + console.log( + `โž• Starting INSERTION for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data & Survey Data '} Collections...` + ) + console.log(`=================================================`) + + for (const item of collectionsToInsert) { + if (item.data) { + await insertData(item.name, item.data, item.db) + } + } +} + +main({ dataToBeInserted: entityData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Entity data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + +main({ dataToBeInserted: projectData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Project data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + + +main({ dataToBeInserted: surveyData }) +.then(() => { + console.log('\n=======================================') + console.log('โœ… survey data population process finished.') + console.log('=======================================') +}) +.catch(console.error) diff --git a/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js b/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js new file mode 100644 index 00000000..585a7fb4 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js @@ -0,0 +1,1929 @@ +const { ObjectId } = require('mongodb') + +let solutionData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + entityType: 'school', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + name: 'pro with obsasatask oct 8 facilitator only 2nd', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programName: 'custom observation as a task check on oct 14th facilitator', + programDescription: 'custom observation as a task check on oct 14th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.993Z'), + createdAt: new Date('2025-10-14T13:10:11.897Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + link: 'f8a8e9ba397a29cf75ad5057db6cb7f9', + }, + { + _id: new ObjectId('68e8c635201642091e014914'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + entityType: 'school', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + name: 'Testing Project For LED IMP facilitator only', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68e8c284201642091e0148c1'), + programName: 'custom observation as a task check on oct 10th facilitator', + programDescription: 'custom observation as a task check on oct 10th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.617Z'), + createdAt: new Date('2025-10-10T08:39:17.519Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + link: '178ac1fdff5b367ef3335ce0e1665a6c', + }, + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'ProgramTestKey1', + entityType: 'school', + externalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + name: 'Project name sep 16 9 30', + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-01-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programName: 'Program name is sep 16 9 30', + programDescription: 'Description of the Program', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.599Z'), + createdAt: new Date('2025-09-16T16:17:25.472Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['ALL'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + }, + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + entityType: 'school', + externalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + name: 'project sup test with obs or sur tasks sep 23 1520', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-12-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programName: 'SUP_as_a_task_test_sept_24_1500', + programDescription: 'This is the description of the program.', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:19.783Z'), + createdAt: new Date('2025-09-24T09:28:07.900Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL', '6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + link: 'a0acc357edbcf3287e9767d20a7d9f12', + }, +] + +let programData = [ + { + _id: new ObjectId('68ee4b79fb9bee08b93b6d34'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + name: 'custom observation as a task check on oct 14th facilitator', + description: 'custom observation as a task check on oct 14th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:18:46.936Z'), + createdAt: new Date('2025-10-14T13:09:13.649Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68e8c284201642091e0148c1'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68e8c635201642091e014914'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + name: 'custom observation as a task check on oct 10th facilitator', + description: 'custom observation as a task check on oct 10th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:44:35.535Z'), + createdAt: new Date('2025-10-10T08:23:32.295Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68c98d8f38aee0086ee61070'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'ProgramTestKey1', + name: 'Program name is sep 16 9 30', + description: 'Description of the Program', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials', 'teacher-educators-coordinators'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-01-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T17:06:14.752Z'), + createdAt: new Date('2025-09-16T16:17:19.239Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68d3b9681e09f9b5b1e0693d'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'SUP_as_a_task_test_sept_24_1500', + name: 'SUP_as_a_task_test_sept_24_1500 oct 3', + description: 'This is the description of the program.', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-12-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-03T09:20:39.907Z'), + createdAt: new Date('2025-09-24T09:27:04.322Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + },, + { + _id: new ObjectId("691c1b06e71d83091cf9c336"), + resourceType: ["program"], + language: ["English"], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId("691c1b10e71d83091cf9c35d"), + order: 1, + }, + { + _id: new ObjectId("691c1b17266ef5649ce4104c"), + order: 2, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c474"), + order: 3, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c495"), + order: 4, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4b6"), + order: 5, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4da"), + order: 6, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4fb"), + order: 7, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c51c"), + order: 8, + }, + { + _id: new ObjectId("691c1f96266ef5649ce41171"), + order: 9, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: "active", + owner: "1", + createdBy: "1", + updatedBy: "1", + externalId: "Testing_for_creation_sup_18_11", + name: "Testing for creation sup 18-11", + description: "This is the description of the program.", + metaInformation: { + state: ["Tripura"], + recommendedFor: ["student"], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date("2025-11-16T18:30:00.000Z"), + endDate: new Date("2030-11-28T18:29:59.000Z"), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date("2025-11-18T07:26:14.940Z"), + createdAt: new Date("2025-11-18T07:06:46.613Z"), + __v: 0, + scope: { + professional_role: ["6867a3c10d8d24001465c2d1"], + professional_subroles: ["6867a1420d8d24001465c28f"], + state: ["6863a9941d52e30014093ad9"], + district: ["6863aa5f1d52e30014093b41"], + block: ["ALL"], + cluster: ["ALL"], + school: ["ALL"], + }, + }, + { + _id: new ObjectId("691b10a0dbb768073d67328c"), + resourceType: ["program"], + language: ["English"], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId("691b141a1ce3f5956e9f30e8"), + order: 1, + }, + { + _id: new ObjectId("691b1783dbb768073d67330d"), + order: 2, + }, + { + _id: new ObjectId("691b1790dbb768073d673366"), + order: 3, + }, + { + _id: new ObjectId("691b179e7b8c31191b8facee"), + order: 4, + }, + { + _id: new ObjectId("691b17ae1ce3f5956e9f319d"), + order: 5, + }, + { + _id: new ObjectId("691b192a1ce3f5956e9f320e"), + order: 6, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: "active", + owner: "1", + createdBy: "1", + updatedBy: "1", + externalId: "Testing_for_creation_sup_17_11", + name: "Testing for creation sup 17-11", + description: "This is the description of the program.", + metaInformation: { + state: ["Tripura"], + recommendedFor: ["student"], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date("2025-11-16T18:30:00.000Z"), + endDate: new Date("2030-11-28T18:29:59.000Z"), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date("2025-11-17T12:46:34.713Z"), + createdAt: new Date("2025-11-17T12:10:08.914Z"), + __v: 0, + scope: { + professional_role: ["6867a3c10d8d24001465c2d1"], + professional_subroles: ["6867a1420d8d24001465c28f"], + state: ["6863a9941d52e30014093ad9"], + district: ["6863aa5f1d52e30014093b41"], + block: ["ALL"], + cluster: ["ALL"], + school: ["ALL"], + }, + }, +]; + +let projectTemplatesData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + new ObjectId('68ee4bb4fb9bee08b93b6d82'), + new ObjectId('68ee4bb4fb9bee08b93b6d86'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'pro with obsasatask oct 8 facilitator only 2nd', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.899Z'), + createdAt: new Date('2025-10-14T13:10:11.630Z'), + __v: 0, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + solutionExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + parentTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d4c'), + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + }, + { + _id: new ObjectId('68e8c635201642091e01491c'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68e8c635201642091e014926'), + new ObjectId('68e8c635201642091e01492a'), + new ObjectId('68e8c635201642091e01492e'), + new ObjectId('68e8c635201642091e014932'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'Testing Project For LED IMP facilitator only', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.544Z'), + createdAt: new Date('2025-10-10T08:39:17.260Z'), + __v: 0, + solutionId: new ObjectId('68e8c635201642091e014914'), + solutionExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + programId: new ObjectId('68e8c284201642091e0148c1'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + parentTemplateId: new ObjectId('68e8c635201642091e0148f8'), + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + }, + { + _id: new ObjectId('68c98d9538aee0086ee6109e'), + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: [''], + tasks: [ + new ObjectId('68c98d9538aee0086ee610a2'), + new ObjectId('68c98d9538aee0086ee610a6'), + new ObjectId('68c98d9538aee0086ee610aa'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'Task1-1758039445176-1758039445561', + 'Task2-1758039445176-1758039445567', + 'Task3-1758039445176-1758039445575', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'Project name sep 16 9 30', + externalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.596Z'), + createdAt: new Date('2025-09-16T16:17:25.301Z'), + __v: 0, + solutionId: new ObjectId('68c98d9538aee0086ee61096'), + solutionExternalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programExternalId: 'ProgramTestKey1', + parentTemplateId: new ObjectId('68c98d9538aee0086ee6107a'), + }, + { + _id: new ObjectId('68d3b9a92ba17cc3cb238829'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68d3b9ad2ba17cc3cb238837'), + new ObjectId('68d3b9ad2ba17cc3cb23883b'), + new ObjectId('68d3b9ae2ba17cc3cb23883f'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'project sup test with obs or sur tasks sep 23 1520', + externalId: 'DPDTSCH012025-1758706081315_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:14.561Z'), + createdAt: new Date('2025-09-24T09:28:03.404Z'), + __v: 0, + solutionId: new ObjectId('68d3b9a72ba17cc3cb238821'), + solutionExternalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + parentTemplateId: new ObjectId('68d3b9a32ba17cc3cb238805'), + }, +] + +let projectTemplateTasksData = [ + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.192Z'), + createdAt: new Date('2025-10-14T13:10:11.805Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.202Z'), + createdAt: new Date('2025-10-14T13:10:11.813Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d82'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.210Z'), + createdAt: new Date('2025-10-14T13:10:11.825Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d86'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.218Z'), + createdAt: new Date('2025-10-14T13:10:11.833Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014926'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2026', + endDate: '31/12/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.813Z'), + createdAt: new Date('2025-10-10T08:39:17.430Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2027', + endDate: '31/12/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.822Z'), + createdAt: new Date('2025-10-10T08:39:17.439Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2028', + endDate: '31/12/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.831Z'), + createdAt: new Date('2025-10-10T08:39:17.449Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014932'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2029', + endDate: '31/12/2029', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.840Z'), + createdAt: new Date('2025-10-10T08:39:17.458Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a2'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Manual (PDF)', + link: 'https://docs.google.com/document/d/1NCUdj9nPAz82sPV5q2BJ8At31sFJdSDwocrDCh_g7W0/edit?tab=t.0', + app: 'projectService', + id: 'edit?tab=t.0', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Review the Activity Manual', + externalId: 'Task1-1758039445176-1758039445561', + description: '', + sequenceNumber: '1', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '28/07/2025', + endDate: '30/01/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.564Z'), + createdAt: new Date('2025-09-16T16:17:25.375Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a6'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'Task2-1758039445176-1758039445567', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '29/07/2025', + endDate: '30/01/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.571Z'), + createdAt: new Date('2025-09-16T16:17:25.386Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610aa'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'Task3-1758039445176-1758039445575', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/01/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.579Z'), + createdAt: new Date('2025-09-16T16:17:25.396Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb238837'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.534Z'), + createdAt: new Date('2025-09-24T09:28:06.227Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb23883b'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Assessment (PDF)', + link: 'https://sunbirdsaaspublic.blob.core.windows.net/content/content/assets/do_2143687931908833281255/dpdt-switch-car.pdf', + app: 'projectService', + id: 'dpdt-switch-car.pdf', + }, + { + name: 'Activity OMR Sheet (PDF)', + link: 'https://drive.google.com/file/d/1-f7Tg8bmZd-xlcxlhfOcf2ZO6vpc6qkH/view', + app: 'projectService', + id: 'view', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.967Z'), + createdAt: new Date('2025-09-24T09:28:06.583Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ae2ba17cc3cb23883f'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:14.374Z'), + createdAt: new Date('2025-09-24T09:28:07.083Z'), + __v: 0, + },, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d75"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: "observation", + solutionDetails: { + type: "observation", + subType: "Social Studies", + _id: "68ee4bb440fd155dceef08a9", + externalId: + "fb34d196-a8fe-11f0-9793-553f35f97dd1-OBSERVATION-TEMPLATE-1760447411986", + name: "obsasatask oct 8 facilitator only 2nd", + isReusable: false, + minNoOfSubmissionsRequired: "2.0", + }, + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Review the Activity Manual", + externalId: "DPDTSC-HandBook-1-2025-Task1-1760447411369-1760447411984", + description: "", + sequenceNumber: "1", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "True", + minNoOfSubmissionsRequired: "2.0", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.146Z"), + createdAt: new Date("2025-10-14T13:10:11.744Z"), + __v: 0, + }, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d7e"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: "simple", + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Conduct the Activity with students", + externalId: "DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197", + description: "", + sequenceNumber: "3", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "", + minNoOfSubmissionsRequired: "", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.202Z"), + createdAt: new Date("2025-10-14T13:10:11.813Z"), + __v: 0, + }, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d82"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: "learn", + link: "https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link", + app: "projectService", + id: "view?usp=drive_link", + }, + ], + deleted: false, + type: "content", + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Conduct the Activity Assessment", + externalId: "DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206", + description: "", + sequenceNumber: "4", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "", + minNoOfSubmissionsRequired: "", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.210Z"), + createdAt: new Date("2025-10-14T13:10:11.825Z"), + __v: 0, + }, +]; + +let certificateTemplatesData = [ + { + _id: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d53'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d57'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d5b'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d63'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.793Z'), + createdAt: new Date('2025-10-14T13:11:17.628Z'), + __v: 0, + templateUrl: + 'certificate/aa8529e3-6754-4432-a669-72b73d358e2f/1/7042c718-a1bf-43e3-b296-586de247a440/68ee4bf5fb9bee08b93b6d97/14-9-2025-1760447477692_Dowloaded.svg', + }, + { + _id: new ObjectId('68e8c676201642091e014943'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6||C7)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e0148ff'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014903'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014907'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490b'], + }, + }, + }, + C7: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490f'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68e8c635201642091e014914'), + programId: new ObjectId('68e8c284201642091e0148c1'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.454Z'), + createdAt: new Date('2025-10-10T08:40:22.298Z'), + __v: 0, + templateUrl: + 'certificate/0bcc856d-0145-448c-8188-300ca3f3250e/1/58cfdf3c-f1a2-4a94-bbb5-21dcd7286913/68e8c676201642091e014943/10-9-2025-1760085622353_Dowloaded.svg', + }, +] + +let certificateBaseTemplatesData = [ + { + _id: new ObjectId('68c008dfd113c30c11f1aca2'), + deleted: false, + code: 'onelogo_onesign', + name: 'onelogo_onesign', + url: 'certificate/ef2058a1-92e0-4a63-af5f-b712f992bf90/1/81fc35ad-9519-4ec4-87bb-6cef64b940f0/9-8-2025-1757415647754_sl_s1l1.svg', + tenantId: 'default', + orgId: 'slorg', + updatedAt: new Date('2025-09-09T11:00:47.878Z'), + createdAt: new Date('2025-09-09T11:00:47.878Z'), + __v: 0, + }, +] + +let projectCategoriesData = [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + isDeleted: false, + isVisible: true, + status: 'active', + icon: '', + noOfProjects: 361, + evidences: [], + deleted: false, + name: 'teachers', + externalId: 'teachers', + tenantId: 'default', + orgId: 'slorg', + updatedAt: new Date('2025-06-24T17:55:44.720Z'), + createdAt: new Date('2025-06-24T17:55:44.720Z'), + __v: 0, + }, +] + +let configurationData = [ + { + _id: new ObjectId('6825a1982d46aa6df0cc36a8'), + code: 'keysAllowedForTargeting', + __v: 0, + createdAt: new Date('2025-05-15T08:11:04.674Z'), + meta: { + profileKeys: [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_role', + 'professional_subroles', + 'roles', + 'subject', + 'organizations', + ], + }, + updatedAt: new Date('2025-05-26T10:56:17.021Z'), + }, +] + +let organizationExtensionData = [ + { + _id: new ObjectId('68d397cac4872dbaf23b7a15'), + projectResourceVisibilityPolicy: 'CURRENT', + externalProjectResourceVisibilityPolicy: 'CURRENT', + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + deleted: false, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T07:03:38.171Z'), + createdAt: new Date('2025-09-24T07:03:38.171Z'), + __v: 0, + }, +] +module.exports = { + solutionData, + programData, + projectTemplatesData, + projectTemplateTasksData, + certificateTemplatesData, + certificateBaseTemplatesData, + projectCategoriesData, + configurationData, + organizationExtensionData +} diff --git a/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js b/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js new file mode 100644 index 00000000..ec74f678 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js @@ -0,0 +1,5322 @@ +const { ObjectId } = require("mongodb"); + +let solutionData = [ + { + _id: new ObjectId("691c1b17266ef5649ce4104c"), + externalId: "691c1b15266ef5649ce4100d_CHILD", + isReusable: false, + name: "Observation led imp fro sanity 18-11", + description: "Classrom Observation for Selection of Sectors", + author: "2", + parentSolutionId: new ObjectId("691c1b15266ef5649ce4100d"), + resourceType: ["Observations Framework"], + language: ["English"], + keywords: ["Framework", "Observation", "English"], + concepts: [], + scoringSystem: "pointsBasedScoring", + levelToScoreMapping: { + L1: { + points: 10, + label: "Level 1", + }, + L2: { + points: 20, + label: "Level 2", + }, + L3: { + points: 30, + label: "Level 3", + }, + }, + themes: [ + { + name: "Domain 1", + type: "theme", + label: "theme", + externalId: "D1", + weightage: 1, + criteria: [ + { + criteriaId: new ObjectId("691c1b17266ef5649ce41042"), + weightage: 1, + }, + ], + rubric: { + expressionVariables: { + SCORE: "D1.sumOfPointsOfAllChildren()", + }, + levels: { + L1: { + expression: "(20<=SCORE<=35)", + }, + L2: { + expression: "(35&2 + echo "Usage: $0 " >&2 + exit 1 +fi + +# Use the provided folder name +FOLDER_NAME="$1" +DEV_DATABASE_URL="$2" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." >&2 + exit 1 +fi + +# --- 2. HIGHLY RELIABLE DATABASE URL PARSING --- +echo "Parsing database URL..." + +# Remove the protocol part (e.g., 'postgres://') +DB_CLEAN_URL=$(echo "$DEV_DATABASE_URL" | sed 's/.*:\/\///') + +# 1. Extract DB_NAME (last part after the final slash) +DB_NAME=$(echo "$DB_CLEAN_URL" | awk -F '/' '{print $NF}') +# 2. Extract HOST and PORT (remove DB_NAME and the preceding slash) +HOST_PORT_PATH=$(echo "$DB_CLEAN_URL" | sed "s/\/$DB_NAME//") + +# 3. Use standard ':' and '@' delimiters on the remaining string +DB_USER=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $1}') +DB_PASSWORD=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $2}') +DB_HOST=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $3}') +DB_PORT=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $4}') + +# Define the container name (assumes container name is the DB_HOST, which is 'citus_master') +CONTAINER_NAME="$DB_HOST" + +# Log database variables (excluding password) +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "" + +# Check the extracted port +if [[ -z "$DB_PORT" ]]; then + echo "Error: Could not extract database port. Check URL format." >&2 + exit 1 +fi + +# --- 3. WAIT FOR CONTAINER AND DATABASE --- + +# Wait for Docker container to be up +echo "Waiting for Docker container '$CONTAINER_NAME' to be up..." +until docker inspect "$CONTAINER_NAME" &>/dev/null; do + echo -n "." + sleep 1 +done +echo -e "\nContainer is now up." + +# Wait for PostgreSQL to be ready to accept connections +# Use DB_USER for the check, as it must be a valid user +echo "Waiting for PostgreSQL on '$DB_HOST:$DB_PORT' to accept connections..." +until docker exec "$CONTAINER_NAME" bash -c "pg_isready -h localhost -p $DB_PORT -U $DB_USER > /dev/null 2>&1"; do + echo -n "." + sleep 1 +done +echo -e "\nDatabase server is ready." + +# Check and wait for the target database to exist +echo "Checking existence of database '$DB_NAME'..." +until docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d postgres -p $DB_PORT -lqt | grep -qw '$DB_NAME'"; do + echo -n "." + sleep 5 +done +echo -e "\nDatabase '$DB_NAME' exists, proceeding with script." + +# --- 4. CITUS EXTENSION SETUP --- + +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." >&2 + exit 1 +fi + +echo "Copying distributionColumns.sql to container '$CONTAINER_NAME'..." +CONTAINER_SQL_PATH="/tmp/distributionColumns.sql" +docker cp "$DISTRIBUTION_COLUMNS_FILE" "$CONTAINER_NAME:$CONTAINER_SQL_PATH" + +echo "Creating Citus extension in the database..." +docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c 'CREATE EXTENSION IF NOT EXISTS citus;'" + +# --- 5. EXECUTE SQL FILE WITH ROBUST TABLE CHECK --- + +check_table() { + local table_name=$1 + # Check if we can select from the table. If we can't, it returns non-zero. + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -q -t --set ON_ERROR_STOP=1 -c \"SELECT 1 FROM $table_name LIMIT 1;\"" > /dev/null 2>&1 +} + +echo "Starting creation of distributed tables..." +docker exec "$CONTAINER_NAME" bash -c "cat $CONTAINER_SQL_PATH" | while IFS= read -r line; do + trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + if [[ "$trimmed_line" =~ ^create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Processing table: '$table'" + + # Robust wait loop for the table to be created by the preceding process (e.g., migration) + until check_table "$table"; do + echo "Table '$table' does not exist yet (waiting for migration to finish)..." + sleep 1 + done + + echo "Table '$table' exists. Executing Citus distribution command..." + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c \"$trimmed_line\"" + fi +done + +# Clean up temporary file in the container +docker exec "$CONTAINER_NAME" rm "$CONTAINER_SQL_PATH" + +echo "โœ… Citus extension setup and distribution columns complete successfully!" \ No newline at end of file diff --git a/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js b/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js new file mode 100644 index 00000000..8bcbfcb6 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js @@ -0,0 +1,290 @@ +const { ObjectId } = require('mongodb') + +let entityType = [ + { + _id: new ObjectId('6825914b97b5680013e6a140'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'state', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:31.680Z'), + createdAt: new Date('2025-05-15T07:01:31.680Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('6825915197b5680013e6a142'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'district', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:37.892Z'), + createdAt: new Date('2025-05-15T07:01:37.892Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591cc97b5680013e6a15c'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'professional_role', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:40.376Z'), + createdAt: new Date('2025-05-15T07:03:40.376Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591d397b5680013e6a15e'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'professional_subroles', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:47.062Z'), + createdAt: new Date('2025-05-15T07:03:47.062Z'), + __v: 0, + orgId: 'default_code', + }, +] + +let entities = [ + { + _id: new ObjectId('6852c86c7248c20014b38a4d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16', + name: 'Tripura', + }, + childHierarchyPath: ['district', 'block', 'cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825914b97b5680013e6a140'), + entityType: 'state', + registryDetails: { + code: '16', + locationId: '16', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:29:00.266Z'), + createdAt: new Date('2025-06-18T14:08:44.438Z'), + __v: 0, + groups: { + district: [new ObjectId('6852c8ae7248c20014b38a57')], + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8ae7248c20014b38a57'), + metaInformation: { + targetedEntityTypes: [], + externalId: 'westTripura', + name: 'West Tripura', + }, + childHierarchyPath: ['block', 'cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915197b5680013e6a142'), + entityType: 'district', + registryDetails: { + code: 'westTripura', + locationId: 'westTripura', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:27:43.218Z'), + createdAt: new Date('2025-06-18T14:09:50.337Z'), + __v: 0, + groups: { + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8de7248c20014b38a9d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '160101', + name: 'AGARTALA MUNICIPAL COORPORATION', + }, + childHierarchyPath: ['cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915597b5680013e6a144'), + entityType: 'block', + registryDetails: { + code: '160101', + locationId: '160101', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:24:30.469Z'), + createdAt: new Date('2025-06-18T14:10:38.736Z'), + __v: 0, + groups: { + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9027248c20014b38c34'), + metaInformation: { + targetedEntityTypes: [], + externalId: '1601010004', + name: 'ACHARYA PRAFULLA CHANDRA H/S SCHOOL', + }, + childHierarchyPath: ['school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915897b5680013e6a146'), + entityType: 'cluster', + registryDetails: { + code: '1601010004', + locationId: '1601010004', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:22:16.044Z'), + createdAt: new Date('2025-06-18T14:11:14.746Z'), + __v: 0, + groups: { + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9237248c20014b39fa0'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16010100422', + name: 'ABINASH GOPE SMRITI (SAROJANI) JB SCHOOL', + }, + childHierarchyPath: [], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915c97b5680013e6a148'), + entityType: 'school', + registryDetails: { + code: '16010100422', + locationId: '16010100422', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:11:49.194Z'), + createdAt: new Date('2025-06-18T14:11:49.194Z'), + __v: 0, + }, + { + _id: new ObjectId('68876746b19aea00144c2af9'), + metaInformation: { + targetedEntityTypes: [ + { + entityTypeId: '6825915197b5680013e6a142', + entityType: 'district', + }, + ], + externalId: 'Facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_role', 'professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591cc97b5680013e6a15c'), + entityType: 'professional_role', + registryDetails: { + locationId: 'Facilitator', + code: 'Facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-28T12:08:56.065Z'), + createdAt: new Date('2025-07-28T12:04:22.011Z'), + __v: 0, + groups: { + professional_subroles: [new ObjectId('688767deb19aea00144c2b08')], + }, + }, + { + _id: new ObjectId('688767deb19aea00144c2b08'), + metaInformation: { + targetedEntityTypes: [ + { + entityType: 'Handbook1_Activity', + entityTypeId: '688762feb19aea00144c2a81', + }, + { + entityType: 'Handbook2_Activity', + entityTypeId: '68887766b19aea00144c3631', + }, + ], + externalId: 'facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591d397b5680013e6a15e'), + entityType: 'professional_subroles', + registryDetails: { + locationId: 'facilitator', + code: 'facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-29T07:28:05.355Z'), + createdAt: new Date('2025-07-28T12:06:54.072Z'), + __v: 0, + }, +] + +module.exports = { + entities, + entityType, +} diff --git a/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js b/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js new file mode 100644 index 00000000..4e2ef863 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js @@ -0,0 +1,185 @@ +const { MongoClient } = require('mongodb') + +const url = 'mongodb://localhost:27017/' // MongoDB URL +const projectDB = 'elevate-project' +const entityDB = 'elevate-entity' +const entityData = require('./entity_sampleData.js') +const projectData = require('./project_sampleData.js') + +// MongoDB Error Code for Duplicate Key +const DUPLICATE_KEY_ERROR_CODE = 11000 + +// --- UTILITY FUNCTIONS --- + +/** + * Drops the specified collection, effectively deleting all data. + * @param {string} collectionName The name of the collection to drop. + * @param {string} currentDB The name of the database. + */ +async function cleanData(collectionName, currentDB) { + const client = new MongoClient(url) + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const exists = await collection.findOne({}) + if (exists) { + await collection.drop() + console.log(`๐Ÿ—‘๏ธ Successfully dropped collection: ${currentDB}.${collectionName}`) + } else { + // Use .listCollections for a more definitive check if needed, but drop() is usually safe. + console.log(`โ„น๏ธ Collection ${collectionName} in ${currentDB} does not exist or is empty. Skipping drop.`) + } + } catch (error) { + // This catches general connection or other drop errors + console.error(`โŒ Error dropping collection ${collectionName} in ${currentDB}: ${error.message}`) + } finally { + await client.close() + } +} + +/** + * Inserts data into the specified collection and provides detailed status messages. + * (This function is kept the same as your previous version for insertion logic) + * @param {string} collectionName The name of the collection. + * @param {Array} dataFile The array of documents to insert. + * @param {string} currentDB The name of the database. + */ +async function insertData(collectionName, dataFile, currentDB = projectDB) { + const client = new MongoClient(url) + + try { + // Connect to MongoDB + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const data = dataFile + + if (!data || data.length === 0) { + return + } + + console.log(`\n--- Attempting insertion into: ${currentDB}.${collectionName} ---`) + + const results = [] + + // Use Promise.all with map for concurrent insertion (faster) + await Promise.all( + data.map(async (doc, index) => { + const tempId = doc._id || `(Document Index: ${index})` + + try { + const result = await collection.insertOne(doc) + + // The _id is either the one from the source doc or the generated one + const finalId = result.insertedId || doc._id + + results.push({ + id: finalId, + status: 'SUCCESS', + message: `Document successfully created with _id: ${finalId}`, + }) + } catch (error) { + if (error.code === DUPLICATE_KEY_ERROR_CODE) { + // This typically happens if the document has an _id or a unique index violation + results.push({ + id: tempId, + status: 'DUPLICATE', + message: `The data with identifier ${tempId} is already present in the DB. Please ensure unique identifiers are provided or clean the existing data.`, + }) + } else { + // Catch other errors (e.g., validation failure, connection issues) + results.push({ + id: tempId, + status: 'FAILURE', + message: `Error inserting document ${tempId}: ${error.message}`, + }) + } + } + }) + ) + + // Print the detailed results + results.forEach((res) => { + let message = '' + if (res.status === 'SUCCESS') { + message = `โœ… SUCCESS: ${res.message}` + } else if (res.status === 'DUPLICATE') { + message = `โš ๏ธ DUPLICATE: ${res.message}` + } else { + message = `โŒ FAILURE: ${res.message}` + } + console.log(message) + }) + } catch (globalError) { + console.error(`\nFatal error connecting to or operating on the database: ${globalError.message}`) + } finally { + await client.close() + } +} + +// --- MAIN EXECUTION LOGIC --- + +async function main({ dataToBeInserted }) { + const collectionsToInsert = [ + { name: 'entities', data: dataToBeInserted.entities, db: entityDB }, + { name: 'entityTypes', data: dataToBeInserted.entityType, db: entityDB }, + { name: 'programs', data: dataToBeInserted.programData, db: projectDB }, + { name: 'solutions', data: dataToBeInserted.solutionData, db: projectDB }, + { name: 'projectTemplates', data: dataToBeInserted.projectTemplatesData, db: projectDB }, + { name: 'projectTemplateTasks', data: dataToBeInserted.projectTemplateTasksData, db: projectDB }, + { name: 'certificateTemplates', data: dataToBeInserted.certificateTemplatesData, db: projectDB }, + { name: 'certificateBaseTemplates', data: dataToBeInserted.certificateBaseTemplatesData, db: projectDB }, + { name: 'projectCategories', data: dataToBeInserted.projectCategoriesData, db: projectDB }, + { name: 'configurations', data: dataToBeInserted.configurationData, db: projectDB }, + { name: 'organizationExtension', data: dataToBeInserted.organizationExtensionData, db: projectDB }, + ] + + console.log(`\n=================================================`) + console.log( + `๐Ÿ—‘๏ธ Starting CLEANUP for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data'} Collections...` + ) + console.log(`=================================================`) + + // 1. CLEANUP PHASE: Drop all relevant collections first + for (const item of collectionsToInsert) { + // Only call cleanData if there is corresponding data to be inserted, to avoid dropping unrelated collections + if (item.data) { + await cleanData(item.name, item.db) + } + } + + console.log(`\n=================================================`) + console.log( + `โž• Starting INSERTION for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data'} Collections...` + ) + console.log(`=================================================`) + + // 2. INSERTION PHASE: Insert new data + for (const item of collectionsToInsert) { + if (item.data) { + // The insertData function already handles the database selection via the last argument + await insertData(item.name, item.data, item.db) + } + } +} + +// --- EXECUTION CALLS --- + +main({ dataToBeInserted: entityData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Entity data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + +main({ dataToBeInserted: projectData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Project data population process finished.') + console.log('=======================================') + }) + .catch(console.error) diff --git a/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js b/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js new file mode 100644 index 00000000..c97df6c6 --- /dev/null +++ b/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js @@ -0,0 +1,1649 @@ +const { ObjectId } = require('mongodb') + +let solutionData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + entityType: 'school', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + name: 'pro with obsasatask oct 8 facilitator only 2nd', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programName: 'custom observation as a task check on oct 14th facilitator', + programDescription: 'custom observation as a task check on oct 14th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.993Z'), + createdAt: new Date('2025-10-14T13:10:11.897Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + link: 'f8a8e9ba397a29cf75ad5057db6cb7f9', + }, + { + _id: new ObjectId('68e8c635201642091e014914'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + entityType: 'school', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + name: 'Testing Project For LED IMP facilitator only', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68e8c284201642091e0148c1'), + programName: 'custom observation as a task check on oct 10th facilitator', + programDescription: 'custom observation as a task check on oct 10th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.617Z'), + createdAt: new Date('2025-10-10T08:39:17.519Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + link: '178ac1fdff5b367ef3335ce0e1665a6c', + }, + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'ProgramTestKey1', + entityType: 'school', + externalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + name: 'Project name sep 16 9 30', + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2026-01-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programName: 'Program name is sep 16 9 30', + programDescription: 'Description of the Program', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.599Z'), + createdAt: new Date('2025-09-16T16:17:25.472Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['ALL'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + }, + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + entityType: 'school', + externalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + name: 'project sup test with obs or sur tasks sep 23 1520', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2025-12-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programName: 'SUP_as_a_task_test_sept_24_1500', + programDescription: 'This is the description of the program.', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:19.783Z'), + createdAt: new Date('2025-09-24T09:28:07.900Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL', '6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + link: 'a0acc357edbcf3287e9767d20a7d9f12', + }, +] + +let programData = [ + { + _id: new ObjectId('68ee4b79fb9bee08b93b6d34'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + name: 'custom observation as a task check on oct 14th facilitator', + description: 'custom observation as a task check on oct 14th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:18:46.936Z'), + createdAt: new Date('2025-10-14T13:09:13.649Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68e8c284201642091e0148c1'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68e8c635201642091e014914'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + name: 'custom observation as a task check on oct 10th facilitator', + description: 'custom observation as a task check on oct 10th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:44:35.535Z'), + createdAt: new Date('2025-10-10T08:23:32.295Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68c98d8f38aee0086ee61070'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'ProgramTestKey1', + name: 'Program name is sep 16 9 30', + description: 'Description of the Program', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials', 'teacher-educators-coordinators'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2026-01-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T17:06:14.752Z'), + createdAt: new Date('2025-09-16T16:17:19.239Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68d3b9681e09f9b5b1e0693d'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'SUP_as_a_task_test_sept_24_1500', + name: 'SUP_as_a_task_test_sept_24_1500 oct 3', + description: 'This is the description of the program.', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2025-12-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-03T09:20:39.907Z'), + createdAt: new Date('2025-09-24T09:27:04.322Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, +] + +let projectTemplatesData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + new ObjectId('68ee4bb4fb9bee08b93b6d82'), + new ObjectId('68ee4bb4fb9bee08b93b6d86'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'pro with obsasatask oct 8 facilitator only 2nd', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.899Z'), + createdAt: new Date('2025-10-14T13:10:11.630Z'), + __v: 0, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + solutionExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + parentTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d4c'), + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + }, + { + _id: new ObjectId('68e8c635201642091e01491c'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68e8c635201642091e014926'), + new ObjectId('68e8c635201642091e01492a'), + new ObjectId('68e8c635201642091e01492e'), + new ObjectId('68e8c635201642091e014932'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'Testing Project For LED IMP facilitator only', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.544Z'), + createdAt: new Date('2025-10-10T08:39:17.260Z'), + __v: 0, + solutionId: new ObjectId('68e8c635201642091e014914'), + solutionExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + programId: new ObjectId('68e8c284201642091e0148c1'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + parentTemplateId: new ObjectId('68e8c635201642091e0148f8'), + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + }, + { + _id: new ObjectId('68c98d9538aee0086ee6109e'), + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: [''], + tasks: [ + new ObjectId('68c98d9538aee0086ee610a2'), + new ObjectId('68c98d9538aee0086ee610a6'), + new ObjectId('68c98d9538aee0086ee610aa'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'Task1-1758039445176-1758039445561', + 'Task2-1758039445176-1758039445567', + 'Task3-1758039445176-1758039445575', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'Project name sep 16 9 30', + externalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.596Z'), + createdAt: new Date('2025-09-16T16:17:25.301Z'), + __v: 0, + solutionId: new ObjectId('68c98d9538aee0086ee61096'), + solutionExternalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programExternalId: 'ProgramTestKey1', + parentTemplateId: new ObjectId('68c98d9538aee0086ee6107a'), + }, + { + _id: new ObjectId('68d3b9a92ba17cc3cb238829'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68d3b9ad2ba17cc3cb238837'), + new ObjectId('68d3b9ad2ba17cc3cb23883b'), + new ObjectId('68d3b9ae2ba17cc3cb23883f'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'project sup test with obs or sur tasks sep 23 1520', + externalId: 'DPDTSCH012025-1758706081315_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:14.561Z'), + createdAt: new Date('2025-09-24T09:28:03.404Z'), + __v: 0, + solutionId: new ObjectId('68d3b9a72ba17cc3cb238821'), + solutionExternalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + parentTemplateId: new ObjectId('68d3b9a32ba17cc3cb238805'), + }, +] + +let projectTemplateTasksData = [ + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.192Z'), + createdAt: new Date('2025-10-14T13:10:11.805Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.202Z'), + createdAt: new Date('2025-10-14T13:10:11.813Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d82'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.210Z'), + createdAt: new Date('2025-10-14T13:10:11.825Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d86'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.218Z'), + createdAt: new Date('2025-10-14T13:10:11.833Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014926'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2026', + endDate: '31/12/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.813Z'), + createdAt: new Date('2025-10-10T08:39:17.430Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2027', + endDate: '31/12/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.822Z'), + createdAt: new Date('2025-10-10T08:39:17.439Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2028', + endDate: '31/12/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.831Z'), + createdAt: new Date('2025-10-10T08:39:17.449Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014932'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2029', + endDate: '31/12/2029', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.840Z'), + createdAt: new Date('2025-10-10T08:39:17.458Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a2'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Manual (PDF)', + link: 'https://docs.google.com/document/d/1NCUdj9nPAz82sPV5q2BJ8At31sFJdSDwocrDCh_g7W0/edit?tab=t.0', + app: 'projectService', + id: 'edit?tab=t.0', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Review the Activity Manual', + externalId: 'Task1-1758039445176-1758039445561', + description: '', + sequenceNumber: '1', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '28/07/2025', + endDate: '30/01/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.564Z'), + createdAt: new Date('2025-09-16T16:17:25.375Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a6'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'Task2-1758039445176-1758039445567', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '29/07/2025', + endDate: '30/01/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.571Z'), + createdAt: new Date('2025-09-16T16:17:25.386Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610aa'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'Task3-1758039445176-1758039445575', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/01/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.579Z'), + createdAt: new Date('2025-09-16T16:17:25.396Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb238837'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.534Z'), + createdAt: new Date('2025-09-24T09:28:06.227Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb23883b'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Assessment (PDF)', + link: 'https://sunbirdsaaspublic.blob.core.windows.net/content/content/assets/do_2143687931908833281255/dpdt-switch-car.pdf', + app: 'projectService', + id: 'dpdt-switch-car.pdf', + }, + { + name: 'Activity OMR Sheet (PDF)', + link: 'https://drive.google.com/file/d/1-f7Tg8bmZd-xlcxlhfOcf2ZO6vpc6qkH/view', + app: 'projectService', + id: 'view', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.967Z'), + createdAt: new Date('2025-09-24T09:28:06.583Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ae2ba17cc3cb23883f'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:14.374Z'), + createdAt: new Date('2025-09-24T09:28:07.083Z'), + __v: 0, + }, +] + +let certificateTemplatesData = [ + { + _id: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d53'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d57'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d5b'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d63'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.793Z'), + createdAt: new Date('2025-10-14T13:11:17.628Z'), + __v: 0, + templateUrl: + 'certificate/aa8529e3-6754-4432-a669-72b73d358e2f/1/7042c718-a1bf-43e3-b296-586de247a440/68ee4bf5fb9bee08b93b6d97/14-9-2025-1760447477692_Dowloaded.svg', + }, + { + _id: new ObjectId('68e8c676201642091e014943'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6||C7)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e0148ff'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014903'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014907'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490b'], + }, + }, + }, + C7: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490f'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68e8c635201642091e014914'), + programId: new ObjectId('68e8c284201642091e0148c1'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.454Z'), + createdAt: new Date('2025-10-10T08:40:22.298Z'), + __v: 0, + templateUrl: + 'certificate/0bcc856d-0145-448c-8188-300ca3f3250e/1/58cfdf3c-f1a2-4a94-bbb5-21dcd7286913/68e8c676201642091e014943/10-9-2025-1760085622353_Dowloaded.svg', + }, +] + +let certificateBaseTemplatesData = [ + { + _id: new ObjectId('68c008dfd113c30c11f1aca2'), + deleted: false, + code: 'onelogo_onesign', + name: 'onelogo_onesign', + url: 'certificate/ef2058a1-92e0-4a63-af5f-b712f992bf90/1/81fc35ad-9519-4ec4-87bb-6cef64b940f0/9-8-2025-1757415647754_sl_s1l1.svg', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-09T11:00:47.878Z'), + createdAt: new Date('2025-09-09T11:00:47.878Z'), + __v: 0, + }, +] + +let projectCategoriesData = [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + isDeleted: false, + isVisible: true, + status: 'active', + icon: '', + noOfProjects: 361, + evidences: [], + deleted: false, + name: 'teachers', + externalId: 'teachers', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-24T17:55:44.720Z'), + createdAt: new Date('2025-06-24T17:55:44.720Z'), + __v: 0, + visibleToOrganizations: ['default_code'], + }, +] + +let configurationData = [ + { + _id: new ObjectId('6825a1982d46aa6df0cc36a8'), + code: 'keysAllowedForTargeting', + __v: 0, + createdAt: new Date('2025-05-15T08:11:04.674Z'), + meta: { + profileKeys: [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_role', + 'professional_subroles', + 'roles', + 'subject', + 'organizations', + ], + }, + updatedAt: new Date('2025-05-26T10:56:17.021Z'), + }, +] + +let organizationExtensionData = [ + { + _id: new ObjectId('68d397cac4872dbaf23b7a15'), + projectResourceVisibilityPolicy: 'CURRENT', + externalProjectResourceVisibilityPolicy: 'CURRENT', + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + deleted: false, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T07:03:38.171Z'), + createdAt: new Date('2025-09-24T07:03:38.171Z'), + __v: 0, + }, +] +module.exports = { + solutionData, + programData, + projectTemplatesData, + projectTemplateTasksData, + certificateTemplatesData, + certificateBaseTemplatesData, + projectCategoriesData, + configurationData, + organizationExtensionData, +} diff --git a/documentation/3.4.0/common-files/generics/configFile.json b/documentation/3.4.0/common-files/generics/configFile.json new file mode 100644 index 00000000..b3d32b2f --- /dev/null +++ b/documentation/3.4.0/common-files/generics/configFile.json @@ -0,0 +1,11 @@ +{ + "authTokenUserInformation": { + "userId": "data.id", + "userName": "data.name", + "firstName": "data.name", + "organization_id": "data.organization_codes[0]", + "roles": "data.organizations[?code={{organization_id}}].roles", + "organizations": "data.organizations", + "tenant_id": "data.tenant_code" + } +} diff --git a/documentation/3.4.0/common-files/native/project-with-survey/entity_sampleData.js b/documentation/3.4.0/common-files/native/project-with-survey/entity_sampleData.js new file mode 100644 index 00000000..b0b3e335 --- /dev/null +++ b/documentation/3.4.0/common-files/native/project-with-survey/entity_sampleData.js @@ -0,0 +1,290 @@ +const { ObjectId } = require('mongodb') + +let entityType = [ + { + _id: new ObjectId('6825914b97b5680013e6a140'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'state', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:31.680Z'), + createdAt: new Date('2025-05-15T07:01:31.680Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('6825915197b5680013e6a142'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'district', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:37.892Z'), + createdAt: new Date('2025-05-15T07:01:37.892Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591cc97b5680013e6a15c'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'professional_role', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:40.376Z'), + createdAt: new Date('2025-05-15T07:03:40.376Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591d397b5680013e6a15e'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '2', + updatedBy: '2', + deleted: false, + isDeleted: false, + name: 'professional_subroles', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:47.062Z'), + createdAt: new Date('2025-05-15T07:03:47.062Z'), + __v: 0, + orgId: 'default_code', + }, +] + +let entities = [ + { + _id: new ObjectId('6852c86c7248c20014b38a4d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16', + name: 'Tripura', + }, + childHierarchyPath: ['district', 'block', 'cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825914b97b5680013e6a140'), + entityType: 'state', + registryDetails: { + code: '16', + locationId: '16', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:29:00.266Z'), + createdAt: new Date('2025-06-18T14:08:44.438Z'), + __v: 0, + groups: { + district: [new ObjectId('6852c8ae7248c20014b38a57')], + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8ae7248c20014b38a57'), + metaInformation: { + targetedEntityTypes: [], + externalId: 'westTripura', + name: 'West Tripura', + }, + childHierarchyPath: ['block', 'cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915197b5680013e6a142'), + entityType: 'district', + registryDetails: { + code: 'westTripura', + locationId: 'westTripura', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:27:43.218Z'), + createdAt: new Date('2025-06-18T14:09:50.337Z'), + __v: 0, + groups: { + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8de7248c20014b38a9d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '160101', + name: 'AGARTALA MUNICIPAL COORPORATION', + }, + childHierarchyPath: ['cluster', 'school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915597b5680013e6a144'), + entityType: 'block', + registryDetails: { + code: '160101', + locationId: '160101', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:24:30.469Z'), + createdAt: new Date('2025-06-18T14:10:38.736Z'), + __v: 0, + groups: { + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9027248c20014b38c34'), + metaInformation: { + targetedEntityTypes: [], + externalId: '1601010004', + name: 'ACHARYA PRAFULLA CHANDRA H/S SCHOOL', + }, + childHierarchyPath: ['school'], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915897b5680013e6a146'), + entityType: 'cluster', + registryDetails: { + code: '1601010004', + locationId: '1601010004', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:22:16.044Z'), + createdAt: new Date('2025-06-18T14:11:14.746Z'), + __v: 0, + groups: { + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9237248c20014b39fa0'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16010100422', + name: 'ABINASH GOPE SMRITI (SAROJANI) JB SCHOOL', + }, + childHierarchyPath: [], + createdBy: '2', + updatedBy: '2', + deleted: false, + entityTypeId: new ObjectId('6825915c97b5680013e6a148'), + entityType: 'school', + registryDetails: { + code: '16010100422', + locationId: '16010100422', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:11:49.194Z'), + createdAt: new Date('2025-06-18T14:11:49.194Z'), + __v: 0, + }, + { + _id: new ObjectId('68876746b19aea00144c2af9'), + metaInformation: { + targetedEntityTypes: [ + { + entityTypeId: '6825915197b5680013e6a142', + entityType: 'district', + }, + ], + externalId: 'Facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_role', 'professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591cc97b5680013e6a15c'), + entityType: 'professional_role', + registryDetails: { + locationId: 'Facilitator', + code: 'Facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-28T12:08:56.065Z'), + createdAt: new Date('2025-07-28T12:04:22.011Z'), + __v: 0, + groups: { + professional_subroles: [new ObjectId('688767deb19aea00144c2b08')], + }, + }, + { + _id: new ObjectId('688767deb19aea00144c2b08'), + metaInformation: { + targetedEntityTypes: [ + { + entityType: 'Handbook1_Activity', + entityTypeId: '688762feb19aea00144c2a81', + }, + { + entityType: 'Handbook2_Activity', + entityTypeId: '68887766b19aea00144c3631', + }, + ], + externalId: 'facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591d397b5680013e6a15e'), + entityType: 'professional_subroles', + registryDetails: { + locationId: 'facilitator', + code: 'facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-29T07:28:05.355Z'), + createdAt: new Date('2025-07-28T12:06:54.072Z'), + __v: 0, + }, +] + +module.exports = { + entities, + entityType, +} \ No newline at end of file diff --git a/documentation/3.4.0/common-files/native/project-with-survey/insert_sample_solutions.js b/documentation/3.4.0/common-files/native/project-with-survey/insert_sample_solutions.js new file mode 100644 index 00000000..6b02bb98 --- /dev/null +++ b/documentation/3.4.0/common-files/native/project-with-survey/insert_sample_solutions.js @@ -0,0 +1,192 @@ +const { MongoClient } = require('mongodb') + +const url = 'mongodb://localhost:27017/' // MongoDB URL +const projectDB = 'elevate-project' +const entityDB = 'elevate-entity' +const samikshaDB = "elevate-samiksha"; +const entityData = require('./entity_sampleData.js') +const projectData = require('./project_sampleData.js') +const surveyData = require("./survey_sampleData.js"); + +// MongoDB Error Code for Duplicate Key +const DUPLICATE_KEY_ERROR_CODE = 11000 + +// --- UTILITY FUNCTIONS --- + +/** + * Drops the specified collection, effectively deleting all data. + * @param {string} collectionName The name of the collection to drop. + * @param {string} currentDB The name of the database. + */ +async function cleanData(collectionName, currentDB) { + const client = new MongoClient(url) + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const exists = await collection.findOne({}) + if (exists) { + await collection.drop() + console.log(`๐Ÿ—‘๏ธ Successfully dropped collection: ${currentDB}.${collectionName}`) + } else { + // Use .listCollections for a more definitive check if needed, but drop() is usually safe. + console.log(`โ„น๏ธ Collection ${collectionName} in ${currentDB} does not exist or is empty. Skipping drop.`) + } + } catch (error) { + // This catches general connection or other drop errors + console.error(`โŒ Error dropping collection ${collectionName} in ${currentDB}: ${error.message}`) + } finally { + await client.close() + } +} + +/** + * Inserts data into the specified collection and provides detailed status messages. + * (This function is kept the same as your previous version for insertion logic) + * @param {string} collectionName The name of the collection. + * @param {Array} dataFile The array of documents to insert. + * @param {string} currentDB The name of the database. + */ +async function insertData(collectionName, dataFile, currentDB = projectDB) { + const client = new MongoClient(url) + + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const data = dataFile + + if (!data || data.length === 0) { + return + } + + console.log(`\n--- Attempting insertion into: ${currentDB}.${collectionName} ---`) + + const results = [] + await Promise.all( + data.map(async (doc, index) => { + const tempId = doc._id || `(Document Index: ${index})` + + try { + const result = await collection.insertOne(doc) + const finalId = result.insertedId || doc._id + + results.push({ + id: finalId, + status: 'SUCCESS', + message: `Document successfully created with _id: ${finalId}`, + }) + } catch (error) { + if (error.code === DUPLICATE_KEY_ERROR_CODE) { + results.push({ + id: tempId, + status: 'DUPLICATE', + message: `The data with identifier ${tempId} is already present in the DB. Please ensure unique identifiers are provided or clean the existing data.`, + }) + } else { + // Catch other errors (e.g., validation failure, connection issues) + results.push({ + id: tempId, + status: 'FAILURE', + message: `Error inserting document ${tempId}: ${error.message}`, + }) + } + } + }) + ) + + // Print the detailed results + results.forEach((res) => { + let message = '' + if (res.status === 'SUCCESS') { + message = `โœ… SUCCESS: ${res.message}` + } else if (res.status === 'DUPLICATE') { + message = `โš ๏ธ DUPLICATE: ${res.message}` + } else { + message = `โŒ FAILURE: ${res.message}` + } + console.log(message) + }) + } catch (globalError) { + console.error(`\nFatal error connecting to or operating on the database: ${globalError.message}`) + } finally { + await client.close() + } +} + + +async function main({ dataToBeInserted }) { + const collectionsToInsert = [ + { name: 'entities', data: dataToBeInserted.entities, db: entityDB }, + { name: 'entityTypes', data: dataToBeInserted.entityType, db: entityDB }, + { name: 'programs', data: dataToBeInserted.programData, db: projectDB }, + { name: 'solutions', data: dataToBeInserted.solutionData, db: projectDB }, + { name: 'projectTemplates', data: dataToBeInserted.projectTemplatesData, db: projectDB }, + { name: 'projectTemplateTasks', data: dataToBeInserted.projectTemplateTasksData, db: projectDB }, + { name: 'certificateTemplates', data: dataToBeInserted.certificateTemplatesData, db: projectDB }, + { name: 'certificateBaseTemplates', data: dataToBeInserted.certificateBaseTemplatesData, db: projectDB }, + { name: 'projectCategories', data: dataToBeInserted.projectCategoriesData, db: projectDB }, + { name: 'configurations', data: dataToBeInserted.configurationData, db: projectDB }, + { name: 'organizationExtension', data: dataToBeInserted.organizationExtensionData, db: projectDB }, + { name: "solutions", data: dataToBeInserted.solutionData, db:samikshaDB}, + { name: "criteria", data:dataToBeInserted.criteriaData, db : samikshaDB}, + { name: "criteriaQuestions", data: dataToBeInserted.criteriaQuestionsData, db : samikshaDB}, + { name: "frameworks", data: dataToBeInserted.frameworkData, db : samikshaDB}, + { name: "questions", data: dataToBeInserted.questionsData, db : samikshaDB}, + { name: "observations", data: dataToBeInserted.observationData, db : samikshaDB}, + { name: "surveys", data: dataToBeInserted.surveyData, db : samikshaDB}, + { name: "organizationExtension", data: dataToBeInserted.organizationExtensionData, db : samikshaDB}, + + ] + + console.log(`\n=================================================`) + console.log( + `๐Ÿ—‘๏ธ Starting CLEANUP for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data & Survey Data' } Collections...` + ) + console.log(`=================================================`) + + for (const item of collectionsToInsert) { + if (item.data) { + await cleanData(item.name, item.db) + } + } + + console.log(`\n=================================================`) + console.log( + `โž• Starting INSERTION for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data & Survey Data '} Collections...` + ) + console.log(`=================================================`) + + for (const item of collectionsToInsert) { + if (item.data) { + await insertData(item.name, item.data, item.db) + } + } +} + +main({ dataToBeInserted: entityData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Entity data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + +main({ dataToBeInserted: projectData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Project data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + + +main({ dataToBeInserted: surveyData }) +.then(() => { + console.log('\n=======================================') + console.log('โœ… survey data population process finished.') + console.log('=======================================') +}) +.catch(console.error) diff --git a/documentation/3.4.0/common-files/native/project-with-survey/project_sampleData.js b/documentation/3.4.0/common-files/native/project-with-survey/project_sampleData.js new file mode 100644 index 00000000..585a7fb4 --- /dev/null +++ b/documentation/3.4.0/common-files/native/project-with-survey/project_sampleData.js @@ -0,0 +1,1929 @@ +const { ObjectId } = require('mongodb') + +let solutionData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + entityType: 'school', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + name: 'pro with obsasatask oct 8 facilitator only 2nd', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programName: 'custom observation as a task check on oct 14th facilitator', + programDescription: 'custom observation as a task check on oct 14th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.993Z'), + createdAt: new Date('2025-10-14T13:10:11.897Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + link: 'f8a8e9ba397a29cf75ad5057db6cb7f9', + }, + { + _id: new ObjectId('68e8c635201642091e014914'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + entityType: 'school', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + name: 'Testing Project For LED IMP facilitator only', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68e8c284201642091e0148c1'), + programName: 'custom observation as a task check on oct 10th facilitator', + programDescription: 'custom observation as a task check on oct 10th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.617Z'), + createdAt: new Date('2025-10-10T08:39:17.519Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + link: '178ac1fdff5b367ef3335ce0e1665a6c', + }, + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'ProgramTestKey1', + entityType: 'school', + externalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + name: 'Project name sep 16 9 30', + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-01-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programName: 'Program name is sep 16 9 30', + programDescription: 'Description of the Program', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.599Z'), + createdAt: new Date('2025-09-16T16:17:25.472Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['ALL'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + }, + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + entityType: 'school', + externalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + name: 'project sup test with obs or sur tasks sep 23 1520', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-12-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programName: 'SUP_as_a_task_test_sept_24_1500', + programDescription: 'This is the description of the program.', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:19.783Z'), + createdAt: new Date('2025-09-24T09:28:07.900Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL', '6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + link: 'a0acc357edbcf3287e9767d20a7d9f12', + }, +] + +let programData = [ + { + _id: new ObjectId('68ee4b79fb9bee08b93b6d34'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + name: 'custom observation as a task check on oct 14th facilitator', + description: 'custom observation as a task check on oct 14th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:18:46.936Z'), + createdAt: new Date('2025-10-14T13:09:13.649Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68e8c284201642091e0148c1'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68e8c635201642091e014914'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + name: 'custom observation as a task check on oct 10th facilitator', + description: 'custom observation as a task check on oct 10th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2030-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:44:35.535Z'), + createdAt: new Date('2025-10-10T08:23:32.295Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68c98d8f38aee0086ee61070'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'ProgramTestKey1', + name: 'Program name is sep 16 9 30', + description: 'Description of the Program', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials', 'teacher-educators-coordinators'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-01-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T17:06:14.752Z'), + createdAt: new Date('2025-09-16T16:17:19.239Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68d3b9681e09f9b5b1e0693d'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'SUP_as_a_task_test_sept_24_1500', + name: 'SUP_as_a_task_test_sept_24_1500 oct 3', + description: 'This is the description of the program.', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2030-12-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-03T09:20:39.907Z'), + createdAt: new Date('2025-09-24T09:27:04.322Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + },, + { + _id: new ObjectId("691c1b06e71d83091cf9c336"), + resourceType: ["program"], + language: ["English"], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId("691c1b10e71d83091cf9c35d"), + order: 1, + }, + { + _id: new ObjectId("691c1b17266ef5649ce4104c"), + order: 2, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c474"), + order: 3, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c495"), + order: 4, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4b6"), + order: 5, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4da"), + order: 6, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c4fb"), + order: 7, + }, + { + _id: new ObjectId("691c1f96e71d83091cf9c51c"), + order: 8, + }, + { + _id: new ObjectId("691c1f96266ef5649ce41171"), + order: 9, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: "active", + owner: "1", + createdBy: "1", + updatedBy: "1", + externalId: "Testing_for_creation_sup_18_11", + name: "Testing for creation sup 18-11", + description: "This is the description of the program.", + metaInformation: { + state: ["Tripura"], + recommendedFor: ["student"], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date("2025-11-16T18:30:00.000Z"), + endDate: new Date("2030-11-28T18:29:59.000Z"), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date("2025-11-18T07:26:14.940Z"), + createdAt: new Date("2025-11-18T07:06:46.613Z"), + __v: 0, + scope: { + professional_role: ["6867a3c10d8d24001465c2d1"], + professional_subroles: ["6867a1420d8d24001465c28f"], + state: ["6863a9941d52e30014093ad9"], + district: ["6863aa5f1d52e30014093b41"], + block: ["ALL"], + cluster: ["ALL"], + school: ["ALL"], + }, + }, + { + _id: new ObjectId("691b10a0dbb768073d67328c"), + resourceType: ["program"], + language: ["English"], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId("691b141a1ce3f5956e9f30e8"), + order: 1, + }, + { + _id: new ObjectId("691b1783dbb768073d67330d"), + order: 2, + }, + { + _id: new ObjectId("691b1790dbb768073d673366"), + order: 3, + }, + { + _id: new ObjectId("691b179e7b8c31191b8facee"), + order: 4, + }, + { + _id: new ObjectId("691b17ae1ce3f5956e9f319d"), + order: 5, + }, + { + _id: new ObjectId("691b192a1ce3f5956e9f320e"), + order: 6, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: "active", + owner: "1", + createdBy: "1", + updatedBy: "1", + externalId: "Testing_for_creation_sup_17_11", + name: "Testing for creation sup 17-11", + description: "This is the description of the program.", + metaInformation: { + state: ["Tripura"], + recommendedFor: ["student"], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date("2025-11-16T18:30:00.000Z"), + endDate: new Date("2030-11-28T18:29:59.000Z"), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date("2025-11-17T12:46:34.713Z"), + createdAt: new Date("2025-11-17T12:10:08.914Z"), + __v: 0, + scope: { + professional_role: ["6867a3c10d8d24001465c2d1"], + professional_subroles: ["6867a1420d8d24001465c28f"], + state: ["6863a9941d52e30014093ad9"], + district: ["6863aa5f1d52e30014093b41"], + block: ["ALL"], + cluster: ["ALL"], + school: ["ALL"], + }, + }, +]; + +let projectTemplatesData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + new ObjectId('68ee4bb4fb9bee08b93b6d82'), + new ObjectId('68ee4bb4fb9bee08b93b6d86'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'pro with obsasatask oct 8 facilitator only 2nd', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.899Z'), + createdAt: new Date('2025-10-14T13:10:11.630Z'), + __v: 0, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + solutionExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + parentTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d4c'), + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + }, + { + _id: new ObjectId('68e8c635201642091e01491c'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68e8c635201642091e014926'), + new ObjectId('68e8c635201642091e01492a'), + new ObjectId('68e8c635201642091e01492e'), + new ObjectId('68e8c635201642091e014932'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'Testing Project For LED IMP facilitator only', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.544Z'), + createdAt: new Date('2025-10-10T08:39:17.260Z'), + __v: 0, + solutionId: new ObjectId('68e8c635201642091e014914'), + solutionExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + programId: new ObjectId('68e8c284201642091e0148c1'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + parentTemplateId: new ObjectId('68e8c635201642091e0148f8'), + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + }, + { + _id: new ObjectId('68c98d9538aee0086ee6109e'), + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: [''], + tasks: [ + new ObjectId('68c98d9538aee0086ee610a2'), + new ObjectId('68c98d9538aee0086ee610a6'), + new ObjectId('68c98d9538aee0086ee610aa'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'Task1-1758039445176-1758039445561', + 'Task2-1758039445176-1758039445567', + 'Task3-1758039445176-1758039445575', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'Project name sep 16 9 30', + externalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.596Z'), + createdAt: new Date('2025-09-16T16:17:25.301Z'), + __v: 0, + solutionId: new ObjectId('68c98d9538aee0086ee61096'), + solutionExternalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programExternalId: 'ProgramTestKey1', + parentTemplateId: new ObjectId('68c98d9538aee0086ee6107a'), + }, + { + _id: new ObjectId('68d3b9a92ba17cc3cb238829'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68d3b9ad2ba17cc3cb238837'), + new ObjectId('68d3b9ad2ba17cc3cb23883b'), + new ObjectId('68d3b9ae2ba17cc3cb23883f'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'project sup test with obs or sur tasks sep 23 1520', + externalId: 'DPDTSCH012025-1758706081315_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:14.561Z'), + createdAt: new Date('2025-09-24T09:28:03.404Z'), + __v: 0, + solutionId: new ObjectId('68d3b9a72ba17cc3cb238821'), + solutionExternalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + parentTemplateId: new ObjectId('68d3b9a32ba17cc3cb238805'), + }, +] + +let projectTemplateTasksData = [ + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.192Z'), + createdAt: new Date('2025-10-14T13:10:11.805Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.202Z'), + createdAt: new Date('2025-10-14T13:10:11.813Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d82'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.210Z'), + createdAt: new Date('2025-10-14T13:10:11.825Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d86'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.218Z'), + createdAt: new Date('2025-10-14T13:10:11.833Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014926'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2026', + endDate: '31/12/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.813Z'), + createdAt: new Date('2025-10-10T08:39:17.430Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2027', + endDate: '31/12/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.822Z'), + createdAt: new Date('2025-10-10T08:39:17.439Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2028', + endDate: '31/12/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.831Z'), + createdAt: new Date('2025-10-10T08:39:17.449Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014932'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2029', + endDate: '31/12/2029', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.840Z'), + createdAt: new Date('2025-10-10T08:39:17.458Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a2'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Manual (PDF)', + link: 'https://docs.google.com/document/d/1NCUdj9nPAz82sPV5q2BJ8At31sFJdSDwocrDCh_g7W0/edit?tab=t.0', + app: 'projectService', + id: 'edit?tab=t.0', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Review the Activity Manual', + externalId: 'Task1-1758039445176-1758039445561', + description: '', + sequenceNumber: '1', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '28/07/2025', + endDate: '30/01/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.564Z'), + createdAt: new Date('2025-09-16T16:17:25.375Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a6'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'Task2-1758039445176-1758039445567', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '29/07/2025', + endDate: '30/01/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.571Z'), + createdAt: new Date('2025-09-16T16:17:25.386Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610aa'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'Task3-1758039445176-1758039445575', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/01/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.579Z'), + createdAt: new Date('2025-09-16T16:17:25.396Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb238837'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.534Z'), + createdAt: new Date('2025-09-24T09:28:06.227Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb23883b'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Assessment (PDF)', + link: 'https://sunbirdsaaspublic.blob.core.windows.net/content/content/assets/do_2143687931908833281255/dpdt-switch-car.pdf', + app: 'projectService', + id: 'dpdt-switch-car.pdf', + }, + { + name: 'Activity OMR Sheet (PDF)', + link: 'https://drive.google.com/file/d/1-f7Tg8bmZd-xlcxlhfOcf2ZO6vpc6qkH/view', + app: 'projectService', + id: 'view', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.967Z'), + createdAt: new Date('2025-09-24T09:28:06.583Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ae2ba17cc3cb23883f'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:14.374Z'), + createdAt: new Date('2025-09-24T09:28:07.083Z'), + __v: 0, + },, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d75"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: "observation", + solutionDetails: { + type: "observation", + subType: "Social Studies", + _id: "68ee4bb440fd155dceef08a9", + externalId: + "fb34d196-a8fe-11f0-9793-553f35f97dd1-OBSERVATION-TEMPLATE-1760447411986", + name: "obsasatask oct 8 facilitator only 2nd", + isReusable: false, + minNoOfSubmissionsRequired: "2.0", + }, + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Review the Activity Manual", + externalId: "DPDTSC-HandBook-1-2025-Task1-1760447411369-1760447411984", + description: "", + sequenceNumber: "1", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "True", + minNoOfSubmissionsRequired: "2.0", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.146Z"), + createdAt: new Date("2025-10-14T13:10:11.744Z"), + __v: 0, + }, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d7e"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: "simple", + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Conduct the Activity with students", + externalId: "DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197", + description: "", + sequenceNumber: "3", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "", + minNoOfSubmissionsRequired: "", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.202Z"), + createdAt: new Date("2025-10-14T13:10:11.813Z"), + __v: 0, + }, + { + _id: new ObjectId("68ee4bb4fb9bee08b93b6d82"), + createdBy: "1", + updatedBy: "1", + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: "learn", + link: "https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link", + app: "projectService", + id: "view?usp=drive_link", + }, + ], + deleted: false, + type: "content", + projectTemplateId: new ObjectId("68ee4bb3fb9bee08b93b6d70"), + projectTemplateExternalId: + "PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED", + name: "Conduct the Activity Assessment", + externalId: "DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206", + description: "", + sequenceNumber: "4", + tenantId: "default", + orgId: "default_code", + metaInformation: { + hasAParentTask: "NO", + parentTaskOperator: "", + parentTaskValue: "", + parentTaskId: "", + startDate: "01/08/2025", + endDate: "31/12/2025", + isAnExternalTask: "", + minNoOfSubmissionsRequired: "", + redirectLink: "", + buttonLabel: "", + }, + updatedAt: new Date("2025-10-14T13:10:12.210Z"), + createdAt: new Date("2025-10-14T13:10:11.825Z"), + __v: 0, + }, +]; + +let certificateTemplatesData = [ + { + _id: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d53'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d57'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d5b'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d63'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.793Z'), + createdAt: new Date('2025-10-14T13:11:17.628Z'), + __v: 0, + templateUrl: + 'certificate/aa8529e3-6754-4432-a669-72b73d358e2f/1/7042c718-a1bf-43e3-b296-586de247a440/68ee4bf5fb9bee08b93b6d97/14-9-2025-1760447477692_Dowloaded.svg', + }, + { + _id: new ObjectId('68e8c676201642091e014943'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6||C7)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e0148ff'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014903'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014907'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490b'], + }, + }, + }, + C7: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490f'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68e8c635201642091e014914'), + programId: new ObjectId('68e8c284201642091e0148c1'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.454Z'), + createdAt: new Date('2025-10-10T08:40:22.298Z'), + __v: 0, + templateUrl: + 'certificate/0bcc856d-0145-448c-8188-300ca3f3250e/1/58cfdf3c-f1a2-4a94-bbb5-21dcd7286913/68e8c676201642091e014943/10-9-2025-1760085622353_Dowloaded.svg', + }, +] + +let certificateBaseTemplatesData = [ + { + _id: new ObjectId('68c008dfd113c30c11f1aca2'), + deleted: false, + code: 'onelogo_onesign', + name: 'onelogo_onesign', + url: 'certificate/ef2058a1-92e0-4a63-af5f-b712f992bf90/1/81fc35ad-9519-4ec4-87bb-6cef64b940f0/9-8-2025-1757415647754_sl_s1l1.svg', + tenantId: 'default', + orgId: 'slorg', + updatedAt: new Date('2025-09-09T11:00:47.878Z'), + createdAt: new Date('2025-09-09T11:00:47.878Z'), + __v: 0, + }, +] + +let projectCategoriesData = [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + isDeleted: false, + isVisible: true, + status: 'active', + icon: '', + noOfProjects: 361, + evidences: [], + deleted: false, + name: 'teachers', + externalId: 'teachers', + tenantId: 'default', + orgId: 'slorg', + updatedAt: new Date('2025-06-24T17:55:44.720Z'), + createdAt: new Date('2025-06-24T17:55:44.720Z'), + __v: 0, + }, +] + +let configurationData = [ + { + _id: new ObjectId('6825a1982d46aa6df0cc36a8'), + code: 'keysAllowedForTargeting', + __v: 0, + createdAt: new Date('2025-05-15T08:11:04.674Z'), + meta: { + profileKeys: [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_role', + 'professional_subroles', + 'roles', + 'subject', + 'organizations', + ], + }, + updatedAt: new Date('2025-05-26T10:56:17.021Z'), + }, +] + +let organizationExtensionData = [ + { + _id: new ObjectId('68d397cac4872dbaf23b7a15'), + projectResourceVisibilityPolicy: 'CURRENT', + externalProjectResourceVisibilityPolicy: 'CURRENT', + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + deleted: false, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T07:03:38.171Z'), + createdAt: new Date('2025-09-24T07:03:38.171Z'), + __v: 0, + }, +] +module.exports = { + solutionData, + programData, + projectTemplatesData, + projectTemplateTasksData, + certificateTemplatesData, + certificateBaseTemplatesData, + projectCategoriesData, + configurationData, + organizationExtensionData +} diff --git a/documentation/3.4.0/common-files/native/project-with-survey/survey_sampleData.js b/documentation/3.4.0/common-files/native/project-with-survey/survey_sampleData.js new file mode 100644 index 00000000..ec74f678 --- /dev/null +++ b/documentation/3.4.0/common-files/native/project-with-survey/survey_sampleData.js @@ -0,0 +1,5322 @@ +const { ObjectId } = require("mongodb"); + +let solutionData = [ + { + _id: new ObjectId("691c1b17266ef5649ce4104c"), + externalId: "691c1b15266ef5649ce4100d_CHILD", + isReusable: false, + name: "Observation led imp fro sanity 18-11", + description: "Classrom Observation for Selection of Sectors", + author: "2", + parentSolutionId: new ObjectId("691c1b15266ef5649ce4100d"), + resourceType: ["Observations Framework"], + language: ["English"], + keywords: ["Framework", "Observation", "English"], + concepts: [], + scoringSystem: "pointsBasedScoring", + levelToScoreMapping: { + L1: { + points: 10, + label: "Level 1", + }, + L2: { + points: 20, + label: "Level 2", + }, + L3: { + points: 30, + label: "Level 3", + }, + }, + themes: [ + { + name: "Domain 1", + type: "theme", + label: "theme", + externalId: "D1", + weightage: 1, + criteria: [ + { + criteriaId: new ObjectId("691c1b17266ef5649ce41042"), + weightage: 1, + }, + ], + rubric: { + expressionVariables: { + SCORE: "D1.sumOfPointsOfAllChildren()", + }, + levels: { + L1: { + expression: "(20<=SCORE<=35)", + }, + L2: { + expression: "(35&2 + echo "Usage: $0 " >&2 + exit 1 +fi + +# Use the provided folder name +FOLDER_NAME="$1" +DEV_DATABASE_URL="$2" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." >&2 + exit 1 +fi + +# --- 2. HIGHLY RELIABLE DATABASE URL PARSING --- +echo "Parsing database URL..." + +# Remove the protocol part (e.g., 'postgres://') +DB_CLEAN_URL=$(echo "$DEV_DATABASE_URL" | sed 's/.*:\/\///') + +# 1. Extract DB_NAME (last part after the final slash) +DB_NAME=$(echo "$DB_CLEAN_URL" | awk -F '/' '{print $NF}') +# 2. Extract HOST and PORT (remove DB_NAME and the preceding slash) +HOST_PORT_PATH=$(echo "$DB_CLEAN_URL" | sed "s/\/$DB_NAME//") + +# 3. Use standard ':' and '@' delimiters on the remaining string +DB_USER=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $1}') +DB_PASSWORD=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $2}') +DB_HOST=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $3}') +DB_PORT=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $4}') + +# Define the container name (assumes container name is the DB_HOST, which is 'citus_master') +CONTAINER_NAME="$DB_HOST" + +# Log database variables (excluding password) +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "" + +# Check the extracted port +if [[ -z "$DB_PORT" ]]; then + echo "Error: Could not extract database port. Check URL format." >&2 + exit 1 +fi + +# --- 3. WAIT FOR CONTAINER AND DATABASE --- + +# Wait for Docker container to be up +echo "Waiting for Docker container '$CONTAINER_NAME' to be up..." +until docker inspect "$CONTAINER_NAME" &>/dev/null; do + echo -n "." + sleep 1 +done +echo -e "\nContainer is now up." + +# Wait for PostgreSQL to be ready to accept connections +# Use DB_USER for the check, as it must be a valid user +echo "Waiting for PostgreSQL on '$DB_HOST:$DB_PORT' to accept connections..." +until docker exec "$CONTAINER_NAME" bash -c "pg_isready -h localhost -p $DB_PORT -U $DB_USER > /dev/null 2>&1"; do + echo -n "." + sleep 1 +done +echo -e "\nDatabase server is ready." + +# Check and wait for the target database to exist +echo "Checking existence of database '$DB_NAME'..." +until docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d postgres -p $DB_PORT -lqt | grep -qw '$DB_NAME'"; do + echo -n "." + sleep 5 +done +echo -e "\nDatabase '$DB_NAME' exists, proceeding with script." + +# --- 4. CITUS EXTENSION SETUP --- + +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." >&2 + exit 1 +fi + +echo "Copying distributionColumns.sql to container '$CONTAINER_NAME'..." +CONTAINER_SQL_PATH="/tmp/distributionColumns.sql" +docker cp "$DISTRIBUTION_COLUMNS_FILE" "$CONTAINER_NAME:$CONTAINER_SQL_PATH" + +echo "Creating Citus extension in the database..." +docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c 'CREATE EXTENSION IF NOT EXISTS citus;'" + +# --- 5. EXECUTE SQL FILE WITH ROBUST TABLE CHECK --- + +check_table() { + local table_name=$1 + # Check if we can select from the table. If we can't, it returns non-zero. + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -q -t --set ON_ERROR_STOP=1 -c \"SELECT 1 FROM $table_name LIMIT 1;\"" > /dev/null 2>&1 +} + +echo "Starting creation of distributed tables..." +docker exec "$CONTAINER_NAME" bash -c "cat $CONTAINER_SQL_PATH" | while IFS= read -r line; do + trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + if [[ "$trimmed_line" =~ ^create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Processing table: '$table'" + + # Robust wait loop for the table to be created by the preceding process (e.g., migration) + until check_table "$table"; do + echo "Table '$table' does not exist yet (waiting for migration to finish)..." + sleep 1 + done + + echo "Table '$table' exists. Executing Citus distribution command..." + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c \"$trimmed_line\"" + fi +done + +# Clean up temporary file in the container +docker exec "$CONTAINER_NAME" rm "$CONTAINER_SQL_PATH" + +echo "โœ… Citus extension setup and distribution columns complete successfully!" \ No newline at end of file diff --git a/documentation/3.4.0/common-files/native/stand-alone/entity_sampleData.js b/documentation/3.4.0/common-files/native/stand-alone/entity_sampleData.js new file mode 100644 index 00000000..8bcbfcb6 --- /dev/null +++ b/documentation/3.4.0/common-files/native/stand-alone/entity_sampleData.js @@ -0,0 +1,290 @@ +const { ObjectId } = require('mongodb') + +let entityType = [ + { + _id: new ObjectId('6825914b97b5680013e6a140'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'state', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:31.680Z'), + createdAt: new Date('2025-05-15T07:01:31.680Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('6825915197b5680013e6a142'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'district', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:01:37.892Z'), + createdAt: new Date('2025-05-15T07:01:37.892Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591cc97b5680013e6a15c'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'professional_role', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:40.376Z'), + createdAt: new Date('2025-05-15T07:03:40.376Z'), + __v: 0, + orgId: 'default_code', + }, + { + _id: new ObjectId('682591d397b5680013e6a15e'), + profileForm: [], + profileFields: [], + types: [], + callResponseTypes: [], + isObservable: true, + immediateChildrenEntityType: ['district'], + createdBy: '49', + updatedBy: '49', + deleted: false, + isDeleted: false, + name: 'professional_subroles', + toBeMappedToParentEntities: true, + tenantId: 'default', + updatedAt: new Date('2025-05-15T07:03:47.062Z'), + createdAt: new Date('2025-05-15T07:03:47.062Z'), + __v: 0, + orgId: 'default_code', + }, +] + +let entities = [ + { + _id: new ObjectId('6852c86c7248c20014b38a4d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16', + name: 'Tripura', + }, + childHierarchyPath: ['district', 'block', 'cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825914b97b5680013e6a140'), + entityType: 'state', + registryDetails: { + code: '16', + locationId: '16', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:29:00.266Z'), + createdAt: new Date('2025-06-18T14:08:44.438Z'), + __v: 0, + groups: { + district: [new ObjectId('6852c8ae7248c20014b38a57')], + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8ae7248c20014b38a57'), + metaInformation: { + targetedEntityTypes: [], + externalId: 'westTripura', + name: 'West Tripura', + }, + childHierarchyPath: ['block', 'cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915197b5680013e6a142'), + entityType: 'district', + registryDetails: { + code: 'westTripura', + locationId: 'westTripura', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:27:43.218Z'), + createdAt: new Date('2025-06-18T14:09:50.337Z'), + __v: 0, + groups: { + block: [new ObjectId('6852c8de7248c20014b38a9d')], + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c8de7248c20014b38a9d'), + metaInformation: { + targetedEntityTypes: [], + externalId: '160101', + name: 'AGARTALA MUNICIPAL COORPORATION', + }, + childHierarchyPath: ['cluster', 'school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915597b5680013e6a144'), + entityType: 'block', + registryDetails: { + code: '160101', + locationId: '160101', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:24:30.469Z'), + createdAt: new Date('2025-06-18T14:10:38.736Z'), + __v: 0, + groups: { + cluster: [new ObjectId('6852c9027248c20014b38c34')], + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9027248c20014b38c34'), + metaInformation: { + targetedEntityTypes: [], + externalId: '1601010004', + name: 'ACHARYA PRAFULLA CHANDRA H/S SCHOOL', + }, + childHierarchyPath: ['school'], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915897b5680013e6a146'), + entityType: 'cluster', + registryDetails: { + code: '1601010004', + locationId: '1601010004', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:22:16.044Z'), + createdAt: new Date('2025-06-18T14:11:14.746Z'), + __v: 0, + groups: { + school: [new ObjectId('6852c9237248c20014b39fa0')], + }, + }, + { + _id: new ObjectId('6852c9237248c20014b39fa0'), + metaInformation: { + targetedEntityTypes: [], + externalId: '16010100422', + name: 'ABINASH GOPE SMRITI (SAROJANI) JB SCHOOL', + }, + childHierarchyPath: [], + createdBy: '20', + updatedBy: '20', + deleted: false, + entityTypeId: new ObjectId('6825915c97b5680013e6a148'), + entityType: 'school', + registryDetails: { + code: '16010100422', + locationId: '16010100422', + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-18T14:11:49.194Z'), + createdAt: new Date('2025-06-18T14:11:49.194Z'), + __v: 0, + }, + { + _id: new ObjectId('68876746b19aea00144c2af9'), + metaInformation: { + targetedEntityTypes: [ + { + entityTypeId: '6825915197b5680013e6a142', + entityType: 'district', + }, + ], + externalId: 'Facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_role', 'professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591cc97b5680013e6a15c'), + entityType: 'professional_role', + registryDetails: { + locationId: 'Facilitator', + code: 'Facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-28T12:08:56.065Z'), + createdAt: new Date('2025-07-28T12:04:22.011Z'), + __v: 0, + groups: { + professional_subroles: [new ObjectId('688767deb19aea00144c2b08')], + }, + }, + { + _id: new ObjectId('688767deb19aea00144c2b08'), + metaInformation: { + targetedEntityTypes: [ + { + entityType: 'Handbook1_Activity', + entityTypeId: '688762feb19aea00144c2a81', + }, + { + entityType: 'Handbook2_Activity', + entityTypeId: '68887766b19aea00144c3631', + }, + ], + externalId: 'facilitator', + name: 'Facilitator', + }, + childHierarchyPath: ['professional_subroles'], + createdBy: '1', + updatedBy: '1', + deleted: false, + entityTypeId: new ObjectId('682591d397b5680013e6a15e'), + entityType: 'professional_subroles', + registryDetails: { + locationId: 'facilitator', + code: 'facilitator', + }, + userId: '1', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-07-29T07:28:05.355Z'), + createdAt: new Date('2025-07-28T12:06:54.072Z'), + __v: 0, + }, +] + +module.exports = { + entities, + entityType, +} diff --git a/documentation/3.4.0/common-files/native/stand-alone/insert_sample_solutions.js b/documentation/3.4.0/common-files/native/stand-alone/insert_sample_solutions.js new file mode 100644 index 00000000..4e2ef863 --- /dev/null +++ b/documentation/3.4.0/common-files/native/stand-alone/insert_sample_solutions.js @@ -0,0 +1,185 @@ +const { MongoClient } = require('mongodb') + +const url = 'mongodb://localhost:27017/' // MongoDB URL +const projectDB = 'elevate-project' +const entityDB = 'elevate-entity' +const entityData = require('./entity_sampleData.js') +const projectData = require('./project_sampleData.js') + +// MongoDB Error Code for Duplicate Key +const DUPLICATE_KEY_ERROR_CODE = 11000 + +// --- UTILITY FUNCTIONS --- + +/** + * Drops the specified collection, effectively deleting all data. + * @param {string} collectionName The name of the collection to drop. + * @param {string} currentDB The name of the database. + */ +async function cleanData(collectionName, currentDB) { + const client = new MongoClient(url) + try { + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const exists = await collection.findOne({}) + if (exists) { + await collection.drop() + console.log(`๐Ÿ—‘๏ธ Successfully dropped collection: ${currentDB}.${collectionName}`) + } else { + // Use .listCollections for a more definitive check if needed, but drop() is usually safe. + console.log(`โ„น๏ธ Collection ${collectionName} in ${currentDB} does not exist or is empty. Skipping drop.`) + } + } catch (error) { + // This catches general connection or other drop errors + console.error(`โŒ Error dropping collection ${collectionName} in ${currentDB}: ${error.message}`) + } finally { + await client.close() + } +} + +/** + * Inserts data into the specified collection and provides detailed status messages. + * (This function is kept the same as your previous version for insertion logic) + * @param {string} collectionName The name of the collection. + * @param {Array} dataFile The array of documents to insert. + * @param {string} currentDB The name of the database. + */ +async function insertData(collectionName, dataFile, currentDB = projectDB) { + const client = new MongoClient(url) + + try { + // Connect to MongoDB + await client.connect() + const db = client.db(currentDB) + const collection = db.collection(collectionName) + + const data = dataFile + + if (!data || data.length === 0) { + return + } + + console.log(`\n--- Attempting insertion into: ${currentDB}.${collectionName} ---`) + + const results = [] + + // Use Promise.all with map for concurrent insertion (faster) + await Promise.all( + data.map(async (doc, index) => { + const tempId = doc._id || `(Document Index: ${index})` + + try { + const result = await collection.insertOne(doc) + + // The _id is either the one from the source doc or the generated one + const finalId = result.insertedId || doc._id + + results.push({ + id: finalId, + status: 'SUCCESS', + message: `Document successfully created with _id: ${finalId}`, + }) + } catch (error) { + if (error.code === DUPLICATE_KEY_ERROR_CODE) { + // This typically happens if the document has an _id or a unique index violation + results.push({ + id: tempId, + status: 'DUPLICATE', + message: `The data with identifier ${tempId} is already present in the DB. Please ensure unique identifiers are provided or clean the existing data.`, + }) + } else { + // Catch other errors (e.g., validation failure, connection issues) + results.push({ + id: tempId, + status: 'FAILURE', + message: `Error inserting document ${tempId}: ${error.message}`, + }) + } + } + }) + ) + + // Print the detailed results + results.forEach((res) => { + let message = '' + if (res.status === 'SUCCESS') { + message = `โœ… SUCCESS: ${res.message}` + } else if (res.status === 'DUPLICATE') { + message = `โš ๏ธ DUPLICATE: ${res.message}` + } else { + message = `โŒ FAILURE: ${res.message}` + } + console.log(message) + }) + } catch (globalError) { + console.error(`\nFatal error connecting to or operating on the database: ${globalError.message}`) + } finally { + await client.close() + } +} + +// --- MAIN EXECUTION LOGIC --- + +async function main({ dataToBeInserted }) { + const collectionsToInsert = [ + { name: 'entities', data: dataToBeInserted.entities, db: entityDB }, + { name: 'entityTypes', data: dataToBeInserted.entityType, db: entityDB }, + { name: 'programs', data: dataToBeInserted.programData, db: projectDB }, + { name: 'solutions', data: dataToBeInserted.solutionData, db: projectDB }, + { name: 'projectTemplates', data: dataToBeInserted.projectTemplatesData, db: projectDB }, + { name: 'projectTemplateTasks', data: dataToBeInserted.projectTemplateTasksData, db: projectDB }, + { name: 'certificateTemplates', data: dataToBeInserted.certificateTemplatesData, db: projectDB }, + { name: 'certificateBaseTemplates', data: dataToBeInserted.certificateBaseTemplatesData, db: projectDB }, + { name: 'projectCategories', data: dataToBeInserted.projectCategoriesData, db: projectDB }, + { name: 'configurations', data: dataToBeInserted.configurationData, db: projectDB }, + { name: 'organizationExtension', data: dataToBeInserted.organizationExtensionData, db: projectDB }, + ] + + console.log(`\n=================================================`) + console.log( + `๐Ÿ—‘๏ธ Starting CLEANUP for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data'} Collections...` + ) + console.log(`=================================================`) + + // 1. CLEANUP PHASE: Drop all relevant collections first + for (const item of collectionsToInsert) { + // Only call cleanData if there is corresponding data to be inserted, to avoid dropping unrelated collections + if (item.data) { + await cleanData(item.name, item.db) + } + } + + console.log(`\n=================================================`) + console.log( + `โž• Starting INSERTION for ${dataToBeInserted === entityData ? 'Entity Data' : 'Project Data'} Collections...` + ) + console.log(`=================================================`) + + // 2. INSERTION PHASE: Insert new data + for (const item of collectionsToInsert) { + if (item.data) { + // The insertData function already handles the database selection via the last argument + await insertData(item.name, item.data, item.db) + } + } +} + +// --- EXECUTION CALLS --- + +main({ dataToBeInserted: entityData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Entity data population process finished.') + console.log('=======================================') + }) + .catch(console.error) + +main({ dataToBeInserted: projectData }) + .then(() => { + console.log('\n=======================================') + console.log('โœ… Project data population process finished.') + console.log('=======================================') + }) + .catch(console.error) diff --git a/documentation/3.4.0/common-files/native/stand-alone/project_sampleData.js b/documentation/3.4.0/common-files/native/stand-alone/project_sampleData.js new file mode 100644 index 00000000..c97df6c6 --- /dev/null +++ b/documentation/3.4.0/common-files/native/stand-alone/project_sampleData.js @@ -0,0 +1,1649 @@ +const { ObjectId } = require('mongodb') + +let solutionData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + entityType: 'school', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + name: 'pro with obsasatask oct 8 facilitator only 2nd', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programName: 'custom observation as a task check on oct 14th facilitator', + programDescription: 'custom observation as a task check on oct 14th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.993Z'), + createdAt: new Date('2025-10-14T13:10:11.897Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + link: 'f8a8e9ba397a29cf75ad5057db6cb7f9', + }, + { + _id: new ObjectId('68e8c635201642091e014914'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + entityType: 'school', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + name: 'Testing Project For LED IMP facilitator only', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-09-09T00:00:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68e8c284201642091e0148c1'), + programName: 'custom observation as a task check on oct 10th facilitator', + programDescription: 'custom observation as a task check on oct 10th facilitator', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.617Z'), + createdAt: new Date('2025-10-10T08:39:17.519Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + link: '178ac1fdff5b367ef3335ce0e1665a6c', + }, + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'ProgramTestKey1', + entityType: 'school', + externalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + name: 'Project name sep 16 9 30', + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2026-01-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programName: 'Program name is sep 16 9 30', + programDescription: 'Description of the Program', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.599Z'), + createdAt: new Date('2025-09-16T16:17:25.472Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['ALL'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + }, + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + resourceType: ['Improvement Project Solution'], + language: ['English'], + keywords: ['Improvement Project'], + concepts: [], + themes: [], + flattenedThemes: [], + entities: [], + registry: [], + isRubricDriven: false, + enableQuestionReadOut: false, + captureGpsLocationAtQuestionLevel: false, + isAPrivateProgram: false, + allowMultipleAssessemts: false, + isDeleted: false, + pageHeading: 'Domains', + minNoOfSubmissionsRequired: 1, + rootOrganisations: [], + createdFor: [], + submissionLevel: 'USER', + availableForPrivateConsumption: true, + parentEntityKey: null, + deleted: false, + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + entityType: 'school', + externalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + name: 'project sup test with obs or sur tasks sep 23 1520', + description: 'To construct a wired car using a DPDT switch.', + isReusable: false, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2025-12-30T18:29:59.000Z'), + subType: 'improvementProject', + type: 'improvementProject', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programName: 'SUP_as_a_task_test_sept_24_1500', + programDescription: 'This is the description of the program.', + status: 'active', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:19.783Z'), + createdAt: new Date('2025-09-24T09:28:07.900Z'), + __v: 0, + scope: { + professional_role: ['ALL'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['ALL'], + district: ['ALL', '6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + updatedBy: '1', + author: '1', + creator: 'Mallanagouda', + link: 'a0acc357edbcf3287e9767d20a7d9f12', + }, +] + +let programData = [ + { + _id: new ObjectId('68ee4b79fb9bee08b93b6d34'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + name: 'custom observation as a task check on oct 14th facilitator', + description: 'custom observation as a task check on oct 14th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:18:46.936Z'), + createdAt: new Date('2025-10-14T13:09:13.649Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68e8c284201642091e0148c1'), + resourceType: ['program'], + language: ['English'], + keywords: ['CBSE', 'SQAA'], + concepts: [], + components: [ + { + _id: new ObjectId('68e8c635201642091e014914'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + name: 'custom observation as a task check on oct 10th facilitator', + description: 'custom observation as a task check on oct 10th facilitator', + startDate: new Date('2025-09-08T18:30:00.000Z'), + endDate: new Date('2026-09-09T18:29:59.000Z'), + imageCompression: { + quality: 10, + }, + metaInformation: { + state: ['Tripura'], + recommendedFor: ['Facilitator'], + }, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:44:35.535Z'), + createdAt: new Date('2025-10-10T08:23:32.295Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68c98d8f38aee0086ee61070'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68c98d9538aee0086ee61096'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'ProgramTestKey1', + name: 'Program name is sep 16 9 30', + description: 'Description of the Program', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials', 'teacher-educators-coordinators'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2026-01-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T17:06:14.752Z'), + createdAt: new Date('2025-09-16T16:17:19.239Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, + { + _id: new ObjectId('68d3b9681e09f9b5b1e0693d'), + resourceType: ['program'], + language: ['English'], + keywords: [], + concepts: [], + components: [ + { + _id: new ObjectId('68d3b9a72ba17cc3cb238821'), + order: 1, + }, + ], + isAPrivateProgram: false, + isDeleted: false, + requestForPIIConsent: true, + rootOrganisations: [], + createdFor: [], + deleted: false, + status: 'active', + owner: '1', + createdBy: '1', + updatedBy: '1', + externalId: 'SUP_as_a_task_test_sept_24_1500', + name: 'SUP_as_a_task_test_sept_24_1500 oct 3', + description: 'This is the description of the program.', + metaInformation: { + state: ['Tripura'], + recommendedFor: ['functionaries-officials'], + }, + imageCompression: { + quality: 10, + }, + startDate: new Date('2025-07-29T18:30:00.000Z'), + endDate: new Date('2025-12-30T18:29:59.000Z'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-03T09:20:39.907Z'), + createdAt: new Date('2025-09-24T09:27:04.322Z'), + __v: 0, + scope: { + professional_role: ['68876746b19aea00144c2af9'], + professional_subroles: ['688767deb19aea00144c2b08'], + organizations: ['default_code'], + state: ['6852c86c7248c20014b38a4d'], + district: ['6852c8ae7248c20014b38a57'], + block: ['ALL'], + cluster: ['ALL'], + school: ['ALL'], + }, + }, +] + +let projectTemplatesData = [ + { + _id: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + new ObjectId('68ee4bb4fb9bee08b93b6d82'), + new ObjectId('68ee4bb4fb9bee08b93b6d86'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'pro with obsasatask oct 8 facilitator only 2nd', + externalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.899Z'), + createdAt: new Date('2025-10-14T13:10:11.630Z'), + __v: 0, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + solutionExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369-PROJECT-SOLUTION', + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF12SDFGHJ345CVBNMDRGYY', + parentTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d4c'), + certificateTemplateId: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + }, + { + _id: new ObjectId('68e8c635201642091e01491c'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68e8c635201642091e014926'), + new ObjectId('68e8c635201642091e01492a'), + new ObjectId('68e8c635201642091e01492e'), + new ObjectId('68e8c635201642091e014932'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + visibility: 'CURRENT', + visibleToOrganizations: ['default_code'], + deleted: false, + title: 'Testing Project For LED IMP facilitator only', + externalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.544Z'), + createdAt: new Date('2025-10-10T08:39:17.260Z'), + __v: 0, + solutionId: new ObjectId('68e8c635201642091e014914'), + solutionExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008-PROJECT-SOLUTION', + programId: new ObjectId('68e8c284201642091e0148c1'), + programExternalId: 'Testing_for_prTGCEBGFFRYVBDFGJ7DGDGF123456', + parentTemplateId: new ObjectId('68e8c635201642091e0148f8'), + certificateTemplateId: new ObjectId('68e8c676201642091e014943'), + }, + { + _id: new ObjectId('68c98d9538aee0086ee6109e'), + description: + 'Gathers insights from teachers regarding available resources, training needs, and challenges faced in classrooms.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: [''], + tasks: [ + new ObjectId('68c98d9538aee0086ee610a2'), + new ObjectId('68c98d9538aee0086ee610a6'), + new ObjectId('68c98d9538aee0086ee610aa'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'Task1-1758039445176-1758039445561', + 'Task2-1758039445176-1758039445567', + 'Task3-1758039445176-1758039445575', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'Project name sep 16 9 30', + externalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-16T16:17:25.596Z'), + createdAt: new Date('2025-09-16T16:17:25.301Z'), + __v: 0, + solutionId: new ObjectId('68c98d9538aee0086ee61096'), + solutionExternalId: 'ProjectIdtestKey1-1758039445176-PROJECT-SOLUTION', + programId: new ObjectId('68c98d8f38aee0086ee61070'), + programExternalId: 'ProgramTestKey1', + parentTemplateId: new ObjectId('68c98d9538aee0086ee6107a'), + }, + { + _id: new ObjectId('68d3b9a92ba17cc3cb238829'), + description: 'To construct a wired car using a DPDT switch.', + concepts: [''], + keywords: ['Science, Activity Based Learning, STEM Education, STEM Lab, DPDT Switch Car'], + isDeleted: false, + recommendedFor: ['Learner'], + tasks: [ + new ObjectId('68d3b9ad2ba17cc3cb238837'), + new ObjectId('68d3b9ad2ba17cc3cb23883b'), + new ObjectId('68d3b9ae2ba17cc3cb23883f'), + ], + createdBy: '1', + updatedBy: '1', + learningResources: [], + isReusable: false, + taskSequence: [ + 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + ], + averageRating: 0, + noOfRatings: 0, + ratings: { + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + }, + importCount: 0, + evidences: [], + isPrivate: false, + hasSpotlight: false, + hasStory: false, + text: [], + deleted: false, + title: 'project sup test with obs or sur tasks sep 23 1520', + externalId: 'DPDTSCH012025-1758706081315_IMPORTED', + categories: [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + externalId: 'teachers', + name: 'teachers', + }, + ], + entityType: '', + taskCreationForm: '', + durationInDays: 365, + metaInformation: { + testimonials: [], + goal: 'TEMP', + rationale: '', + primaryAudience: '', + duration: '1 year', + successIndicators: '', + risks: '', + approaches: '', + }, + status: 'published', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T09:28:14.561Z'), + createdAt: new Date('2025-09-24T09:28:03.404Z'), + __v: 0, + solutionId: new ObjectId('68d3b9a72ba17cc3cb238821'), + solutionExternalId: 'DPDTSCH012025-1758706081315-PROJECT-SOLUTION', + programId: new ObjectId('68d3b9681e09f9b5b1e0693d'), + programExternalId: 'SUP_as_a_task_test_sept_24_1500', + parentTemplateId: new ObjectId('68d3b9a32ba17cc3cb238805'), + }, +] + +let projectTemplateTasksData = [ + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760447411369-1760447412188', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.192Z'), + createdAt: new Date('2025-10-14T13:10:11.805Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d7e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760447411369-1760447412197', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.202Z'), + createdAt: new Date('2025-10-14T13:10:11.813Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d82'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760447411369-1760447412206', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.210Z'), + createdAt: new Date('2025-10-14T13:10:11.825Z'), + __v: 0, + }, + { + _id: new ObjectId('68ee4bb4fb9bee08b93b6d86'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68ee4bb3fb9bee08b93b6d70'), + projectTemplateExternalId: 'PROJ19099023DGHG789SDASDFGHR4567-1760447411369_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760447411369-1760447412214', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2025', + endDate: '31/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-14T13:10:12.218Z'), + createdAt: new Date('2025-10-14T13:10:11.833Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014926'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'DPDTSC-HandBook-1-2025-Task2-1760085557008-1760085557809', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2026', + endDate: '31/12/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.813Z'), + createdAt: new Date('2025-10-10T08:39:17.430Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492a'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1-2025-Task3-1760085557008-1760085557818', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2027', + endDate: '31/12/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.822Z'), + createdAt: new Date('2025-10-10T08:39:17.439Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e01492e'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'learn', + link: 'https://drive.google.com/file/d/1HOaFxlahxEzc5HOeFqVTw3V_yszmHFbZ/view?usp=drive_link', + app: 'projectService', + id: 'view?usp=drive_link', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1-2025-Task4-1760085557008-1760085557827', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2028', + endDate: '31/12/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.831Z'), + createdAt: new Date('2025-10-10T08:39:17.449Z'), + __v: 0, + }, + { + _id: new ObjectId('68e8c635201642091e014932'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'walking', + link: 'https://drive.google.com/file/d/1eGLKxFb9BaeroTeIOlXoO8XCxyah7fM9/view?usp=sharing', + app: 'projectService', + id: 'view?usp=sharing', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68e8c635201642091e01491c'), + projectTemplateExternalId: 'PROJ190909764HJHF123FGHHcvvbgd-1760085557008_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1-2025-Task5-1760085557008-1760085557835', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '01/08/2029', + endDate: '31/12/2029', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-10-10T08:39:17.840Z'), + createdAt: new Date('2025-10-10T08:39:17.458Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a2'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Manual (PDF)', + link: 'https://docs.google.com/document/d/1NCUdj9nPAz82sPV5q2BJ8At31sFJdSDwocrDCh_g7W0/edit?tab=t.0', + app: 'projectService', + id: 'edit?tab=t.0', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Review the Activity Manual', + externalId: 'Task1-1758039445176-1758039445561', + description: '', + sequenceNumber: '1', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '28/07/2025', + endDate: '30/01/2026', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.564Z'), + createdAt: new Date('2025-09-16T16:17:25.375Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610a6'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Steps (Video)', + link: 'https://youtu.be/MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + app: 'projectService', + id: 'MNvM_H9zD3Y?si=BdfslSzCkmDCggih', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Watch the Activity Video', + externalId: 'Task2-1758039445176-1758039445567', + description: '', + sequenceNumber: '2', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '29/07/2025', + endDate: '30/01/2027', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.571Z'), + createdAt: new Date('2025-09-16T16:17:25.386Z'), + __v: 0, + }, + { + _id: new ObjectId('68c98d9538aee0086ee610aa'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68c98d9538aee0086ee6109e'), + projectTemplateExternalId: 'ProjectIdtestKey1-1758039445176_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'Task3-1758039445176-1758039445575', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/01/2028', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-16T16:17:25.579Z'), + createdAt: new Date('2025-09-16T16:17:25.396Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb238837'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity with students', + externalId: 'DPDTSC-HandBook-1/2025-Task3-1758706081315-1758706093343', + description: '', + sequenceNumber: '3', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.534Z'), + createdAt: new Date('2025-09-24T09:28:06.227Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ad2ba17cc3cb23883b'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [ + { + name: 'Activity Assessment (PDF)', + link: 'https://sunbirdsaaspublic.blob.core.windows.net/content/content/assets/do_2143687931908833281255/dpdt-switch-car.pdf', + app: 'projectService', + id: 'dpdt-switch-car.pdf', + }, + { + name: 'Activity OMR Sheet (PDF)', + link: 'https://drive.google.com/file/d/1-f7Tg8bmZd-xlcxlhfOcf2ZO6vpc6qkH/view', + app: 'projectService', + id: 'view', + }, + ], + deleted: false, + type: 'content', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: 'Conduct the Activity Assessment', + externalId: 'DPDTSC-HandBook-1/2025-Task4-1758706081315-1758706093849', + description: '', + sequenceNumber: '4', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:13.967Z'), + createdAt: new Date('2025-09-24T09:28:06.583Z'), + __v: 0, + }, + { + _id: new ObjectId('68d3b9ae2ba17cc3cb23883f'), + createdBy: '1', + updatedBy: '1', + isDeleted: false, + isDeletable: false, + taskSequence: [], + children: [], + visibleIf: [], + hasSubTasks: false, + learningResources: [], + deleted: false, + type: 'simple', + projectTemplateId: new ObjectId('68d3b9a92ba17cc3cb238829'), + projectTemplateExternalId: 'DPDTSCH012025-1758706081315_IMPORTED', + name: "Log into the scanner app and scan the OMR sheets (check that the students' names are appearing on scanning the OMR)", + externalId: 'DPDTSC-HandBook-1/2025-Task5-1758706081315-1758706094241', + description: '', + sequenceNumber: '5', + tenantId: 'default', + orgId: 'default_code', + metaInformation: { + hasAParentTask: 'NO', + parentTaskOperator: '', + parentTaskValue: '', + parentTaskId: '', + startDate: '30/07/2025', + endDate: '30/12/2025', + isAnExternalTask: '', + minNoOfSubmissionsRequired: '', + redirectLink: '', + buttonLabel: '', + }, + updatedAt: new Date('2025-09-24T09:28:14.374Z'), + createdAt: new Date('2025-09-24T09:28:07.083Z'), + __v: 0, + }, +] + +let certificateTemplatesData = [ + { + _id: new ObjectId('68ee4bf5fb9bee08b93b6d97'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d53'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d57'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d5b'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68ee4bb3fb9bee08b93b6d63'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68ee4bb3fb9bee08b93b6d68'), + programId: new ObjectId('68ee4b79fb9bee08b93b6d34'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-14T13:11:17.793Z'), + createdAt: new Date('2025-10-14T13:11:17.628Z'), + __v: 0, + templateUrl: + 'certificate/aa8529e3-6754-4432-a669-72b73d358e2f/1/7042c718-a1bf-43e3-b296-586de247a440/68ee4bf5fb9bee08b93b6d97/14-9-2025-1760447477692_Dowloaded.svg', + }, + { + _id: new ObjectId('68e8c676201642091e014943'), + status: 'active', + deleted: false, + criteria: { + validationText: 'Complete validation message', + expression: 'C1&&(C3||C4||C5||C6||C7)', + conditions: { + C1: { + validationText: 'Submit your project.', + expression: 'C1', + conditions: { + C1: { + scope: 'project', + key: 'status', + operator: '==', + value: 'submitted', + }, + }, + }, + C3: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e0148ff'], + }, + }, + validationText: 'Add 2 evidence for any task', + }, + C4: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014903'], + }, + }, + }, + C5: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e014907'], + }, + }, + }, + C6: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490b'], + }, + }, + }, + C7: { + expression: 'C1', + conditions: { + C1: { + scope: 'task', + key: 'attachments', + function: 'count', + filter: { + key: 'type', + value: 'all', + }, + operator: '>=', + value: 2, + taskDetails: ['68e8c635201642091e01490f'], + }, + }, + }, + }, + }, + issuer: { + name: 'default_code', + }, + solutionId: new ObjectId('68e8c635201642091e014914'), + programId: new ObjectId('68e8c284201642091e0148c1'), + baseTemplateId: new ObjectId('68c008dfd113c30c11f1aca2'), + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-10-10T08:40:22.454Z'), + createdAt: new Date('2025-10-10T08:40:22.298Z'), + __v: 0, + templateUrl: + 'certificate/0bcc856d-0145-448c-8188-300ca3f3250e/1/58cfdf3c-f1a2-4a94-bbb5-21dcd7286913/68e8c676201642091e014943/10-9-2025-1760085622353_Dowloaded.svg', + }, +] + +let certificateBaseTemplatesData = [ + { + _id: new ObjectId('68c008dfd113c30c11f1aca2'), + deleted: false, + code: 'onelogo_onesign', + name: 'onelogo_onesign', + url: 'certificate/ef2058a1-92e0-4a63-af5f-b712f992bf90/1/81fc35ad-9519-4ec4-87bb-6cef64b940f0/9-8-2025-1757415647754_sl_s1l1.svg', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-09T11:00:47.878Z'), + createdAt: new Date('2025-09-09T11:00:47.878Z'), + __v: 0, + }, +] + +let projectCategoriesData = [ + { + _id: new ObjectId('685ae6a0cb7c7200145dadae'), + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + isDeleted: false, + isVisible: true, + status: 'active', + icon: '', + noOfProjects: 361, + evidences: [], + deleted: false, + name: 'teachers', + externalId: 'teachers', + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-06-24T17:55:44.720Z'), + createdAt: new Date('2025-06-24T17:55:44.720Z'), + __v: 0, + visibleToOrganizations: ['default_code'], + }, +] + +let configurationData = [ + { + _id: new ObjectId('6825a1982d46aa6df0cc36a8'), + code: 'keysAllowedForTargeting', + __v: 0, + createdAt: new Date('2025-05-15T08:11:04.674Z'), + meta: { + profileKeys: [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_role', + 'professional_subroles', + 'roles', + 'subject', + 'organizations', + ], + }, + updatedAt: new Date('2025-05-26T10:56:17.021Z'), + }, +] + +let organizationExtensionData = [ + { + _id: new ObjectId('68d397cac4872dbaf23b7a15'), + projectResourceVisibilityPolicy: 'CURRENT', + externalProjectResourceVisibilityPolicy: 'CURRENT', + createdBy: 'SYSTEM', + updatedBy: 'SYSTEM', + deleted: false, + tenantId: 'default', + orgId: 'default_code', + updatedAt: new Date('2025-09-24T07:03:38.171Z'), + createdAt: new Date('2025-09-24T07:03:38.171Z'), + __v: 0, + }, +] +module.exports = { + solutionData, + programData, + projectTemplatesData, + projectTemplateTasksData, + certificateTemplatesData, + certificateBaseTemplatesData, + projectCategoriesData, + configurationData, + organizationExtensionData, +} diff --git a/documentation/3.4.0/database-diagram/EMS-Entity-Service.drawio.png b/documentation/3.4.0/database-diagram/EMS-Entity-Service.drawio.png new file mode 100644 index 00000000..9f7c2f20 Binary files /dev/null and b/documentation/3.4.0/database-diagram/EMS-Entity-Service.drawio.png differ diff --git a/documentation/3.4.0/database-diagram/EMS-Project-Service.drawio.png b/documentation/3.4.0/database-diagram/EMS-Project-Service.drawio.png new file mode 100644 index 00000000..08d4ed08 Binary files /dev/null and b/documentation/3.4.0/database-diagram/EMS-Project-Service.drawio.png differ diff --git a/documentation/3.4.0/database-diagram/EMS-Samiksha-Service.drawio.png b/documentation/3.4.0/database-diagram/EMS-Samiksha-Service.drawio.png new file mode 100644 index 00000000..869212ae Binary files /dev/null and b/documentation/3.4.0/database-diagram/EMS-Samiksha-Service.drawio.png differ diff --git a/documentation/3.4.0/distribution-columns/user/distributionColumns.sql b/documentation/3.4.0/distribution-columns/user/distributionColumns.sql new file mode 100644 index 00000000..3f7b690d --- /dev/null +++ b/documentation/3.4.0/distribution-columns/user/distributionColumns.sql @@ -0,0 +1,14 @@ +SELECT create_distributed_table('entities', 'entity_type_id'); +SELECT create_distributed_table('entity_types', 'organization_id'); +SELECT create_distributed_table('file_uploads', 'organization_id'); +SELECT create_distributed_table('forms', 'organization_id'); +SELECT create_distributed_table('notification_templates', 'organization_id'); +SELECT create_distributed_table('organizations', 'id'); +SELECT create_distributed_table('organization_codes', 'code'); +SELECT create_distributed_table('organization_domains', 'domain'); +SELECT create_distributed_table('organization_role_requests','organization_id'); +SELECT create_distributed_table('organization_user_invites','organization_id'); +SELECT create_distributed_table('users_credentials','email'); +SELECT create_distributed_table('users', 'organization_id'); +SELECT create_distributed_table('users', 'user_organizations'); +SELECT create_distributed_table('users', 'user_organization_roles'); \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml b/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml new file mode 100644 index 00000000..24cc1f6d --- /dev/null +++ b/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml @@ -0,0 +1,235 @@ +version: '3' +services: + zookeeper: + image: 'confluentinc/cp-zookeeper:7.3.0' + ports: + - '2181:2181' + environment: + - ALLOW_ANONYMOUS_LOGIN=yes + - ZOOKEEPER_CLIENT_PORT=2181 + - ZOOKEEPER_TICK_TIME=2000 + networks: + - project_net + kafka: + image: 'confluentinc/cp-kafka:7.3.0' + ports: + - '9092:9092' + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + depends_on: + - zookeeper + healthcheck: + test: kafka-topics --bootstrap-server localhost:9092 --list || exit 1 + interval: 10s + timeout: 5s + retries: 9 + networks: + - project_net + redis: + image: 'redis:7.0.0' + restart: 'always' + expose: + - 6379 + healthcheck: + test: ['CMD', 'redis-cli', 'ping'] + interval: 10s + timeout: 5s + retries: 5 + networks: + - project_net + project: + image: shikshalokamqa/elevate-project-service:3.4.0 + container_name: project + ports: + - '6000:6000' + environment: + - MONGODB_URL=mongodb://mongo:27017/elevate-project + env_file: + - ./project_env + depends_on: + - mongo + - kafka + volumes: + - ./config.json:/opt/projects/config.json + networks: + - project_net + samiksha: + image: shikshalokamqa/elevate-samiksha-service:3.4.0_RC1 + ports: + - '4301:4301' + command: ['nodemon', 'dev'] + env_file: + - ./samiksha_env + depends_on: + - mongo + volumes: + - ./config.json:/opt/samiksha/config.json + networks: + - project_net + entity_management: + image: shikshalokamqa/elevate-entity-management:3.4 + ports: + - '5001:5001' + env_file: + - ./entity_management_env + depends_on: + - mongo + volumes: + - ./config.json:/var/src/config.json + networks: + - project_net + user: + image: shikshalokamqa/elevate-user:3.4.0 + ports: + - '3001:3001' + command: > + bash -c "echo 'Waiting for PostgreSQL on citus_master:5432 to accept connections...' && + while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/citus_master/5432' 2> /dev/null; do + echo 'Waiting for citus_master to be ready...'; + sleep 1; + done; + echo 'Database is ready.'; + npm run db:init && npm run db:seed:all && + (echo 'Running nodeee' && nodemon app.js &) && + (while ! curl -sSf http://user:3001 > /dev/null; do + sleep 1; + done && echo 'Service is up' && + /bin/bash -c 'cd scripts && echo Running user service scripts && node insertDefaultOrg.js && node viewsScript.js && node -r module-alias/register uploadSampleCSV.js'); + tail -f /dev/null" + depends_on: + - kafka + - citus + - redis + - scheduler + environment: + - DEV_DATABASE_URL=postgres://postgres:postgres@citus_master:5432/user + - KAFKA_URL=kafka:29092 + - REDIS_HOST=redis://redis:6379 + volumes: + - ./user:/usr/src/app + networks: + - project_net + env_file: + - ./user_env + + notification: + image: shikshalokamqa/elevate-notification:2.6.1 + ports: + - '3002:3002' + command: > + bash -c "echo 'Waiting for PostgreSQL on citus_master:5432 to accept connections...' && + while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/citus_master/5432' 2> /dev/null; do + echo 'Waiting for citus_master to be ready...'; + sleep 1; + done; + echo 'Database is ready.'; + npm run db:init && nodemon app.js" + depends_on: + - kafka + - citus + networks: + - project_net + env_file: + - ./notification_env + + scheduler: + image: shikshalokamqa/elevate-scheduler:3.4.0 + ports: + - '4000:4000' + command: ['nodemon', 'app.js'] + depends_on: + kafka: + condition: service_healthy + redis: + condition: service_started + networks: + - project_net + env_file: + - ./scheduler_env + interface: + image: shikshalokamqa/elevate-interface:3.3.2 + ports: + - '3569:3569' + command: ['node', 'app.js'] + depends_on: + kafka: + condition: service_healthy + networks: + - project_net + env_file: + - ./interface_env + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + expose: + - 5432 + environment: &AUTH + POSTGRES_USER: '${POSTGRES_USER:-postgres}' + POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-postgres}' + PGUSER: '${POSTGRES_USER:-postgres}' + PGPASSWORD: '${POSTGRES_PASSWORD:-postgres}' + POSTGRES_DB: 'postgres' + POSTGRES_HOST_AUTH_METHOD: '${POSTGRES_HOST_AUTH_METHOD:-trust}' + POSTGRES_LOG_STATEMENT: 'all' # Enable query logging (set to 'all' for all queries) + networks: + - project_net + #volumes: + # - citus-data:/var/lib/postgresql/data + pgadmin: + image: dpage/pgadmin4 + container_name: elevate-pgadmin + restart: always + ports: + - '5500:80' + environment: + - PGADMIN_DEFAULT_EMAIL=user@shikshalokam.org + - PGADMIN_DEFAULT_PASSWORD=password + networks: + - project_net + mongo: + image: 'mongo:4.4.14' + container_name: project_mongo_1 + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + # volumes: + # - mongo-data:/data/db + # logging: + # driver: none + gotenberg: + image: gotenberg/gotenberg:latest + container_name: gotenberg + ports: + - '3003:3000' + networks: + - project_net + restart: 'always' + + # portal: + # image: shikshalokamqa/elevate-project-obervation-pwa:3.4.0 + # container_name: portal + # ports: + # - '7007:7007' + # volumes: + # - /home/user4/project/env.js:/usr/src/app/www/assets/env/env.js + # command: > + # /bin/bash -c "ionic build --prod && ionic serve --host 0.0.0.0" + # networks: + # - project_net + +networks: + project_net: + external: false +#volumes: +# mongo-data: +# citus-data: diff --git a/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml b/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml new file mode 100644 index 00000000..70879fbb --- /dev/null +++ b/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml @@ -0,0 +1,216 @@ +version: '3' +services: + zookeeper: + image: 'confluentinc/cp-zookeeper:7.3.0' + ports: + - '2181:2181' + environment: + - ALLOW_ANONYMOUS_LOGIN='yes' + - ZOOKEEPER_CLIENT_PORT=2181 + - ZOOKEEPER_TICK_TIME=2000 + networks: + - project_net + kafka: + image: 'confluentinc/cp-kafka:7.3.0' + ports: + - '9092:9092' + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + depends_on: + - zookeeper + healthcheck: + test: kafka-topics --bootstrap-server localhost:9092 --list || exit 1 + interval: 10s + timeout: 5s + retries: 9 + networks: + - project_net + redis: + image: 'redis:7.0.0' + restart: 'always' + expose: + - 6379 + healthcheck: + test: ['CMD', 'redis-cli', 'ping'] + interval: 10s + timeout: 5s + retries: 5 + networks: + - project_net + project: + image: shikshalokamqa/elevate-project-service:3.4.0 + container_name: project + ports: + - '6000:6000' + environment: + - MONGODB_URL=mongodb://mongo:27017/elevate-project + env_file: + - ./project_env + depends_on: + - mongo + - kafka + volumes: + - ./config.json:/opt/projects/config.json + networks: + - project_net + entity_management: + image: shikshalokamqa/elevate-entity-management:3.4 + ports: + - '5001:5001' + env_file: + - ./entity_management_env + depends_on: + - mongo + volumes: + - ./config.json:/var/src/config.json + networks: + - project_net + user: + image: shikshalokamqa/elevate-user:3.4.0 + ports: + - '3001:3001' + command: > + bash -c "echo 'Waiting for PostgreSQL on citus_master:5432 to accept connections...' && + while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/citus_master/5432' 2> /dev/null; do + echo 'Waiting for citus_master to be ready...'; + sleep 1; + done; + echo 'Database is ready.'; + npm run db:init && npm run db:seed:all && + (echo 'Running nodeee' && nodemon app.js &) && + (while ! curl -sSf http://user:3001 > /dev/null; do + sleep 1; + done && echo 'Service is up' && + /bin/bash -c 'cd scripts && echo Running user service scripts && node -r module-alias/register uploadSampleCSV.js'); + tail -f /dev/null" + depends_on: + - kafka + - citus + - redis + - scheduler + environment: + - DEV_DATABASE_URL=postgres://postgres:postgres@citus_master:5432/user + - KAFKA_URL=kafka:9092 + - REDIS_HOST=redis://redis:6379 + volumes: + - ./user:/usr/src/app + networks: + - project_net + env_file: + - ./user_env + + notification: + image: ttpldevops/notification + ports: + - '3002:3002' + depends_on: + citus: + condition: service_started + networks: + - project_net + env_file: + - ./notification_env + scheduler: + image: shikshalokamqa/elevate-scheduler:3.4.0 + ports: + - '4000:4000' + command: ['nodemon', 'app.js'] + depends_on: + kafka: + condition: service_healthy + redis: + condition: service_started + networks: + - project_net + env_file: + - ./scheduler_env + interface: + image: shikshalokamqa/elevate-interface:3.3.2 + ports: + - '3569:3569' + command: ['node', 'app.js'] + depends_on: + kafka: + condition: service_healthy + networks: + - project_net + env_file: + - ./interface_env + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + expose: + - 5432 + environment: &AUTH + POSTGRES_USER: '${POSTGRES_USER:-postgres}' + POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-postgres}' + PGUSER: '${POSTGRES_USER:-postgres}' + PGPASSWORD: '${POSTGRES_PASSWORD:-postgres}' + POSTGRES_DB: 'postgres' + POSTGRES_HOST_AUTH_METHOD: '${POSTGRES_HOST_AUTH_METHOD:-trust}' + POSTGRES_LOG_STATEMENT: 'all' # Enable query logging (set to 'all' for all queries) + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB'] + interval: 5s + timeout: 3s + retries: 5 + networks: + - project_net + #volumes: + # - citus-data:/var/lib/postgresql/data + pgadmin: + image: dpage/pgadmin4 + container_name: elevate-pgadmin + restart: always + ports: + - '5500:80' + environment: + - PGADMIN_DEFAULT_EMAIL=user@shikshalokam.org + - PGADMIN_DEFAULT_PASSWORD=password + networks: + - project_net + mongo: + image: 'mongo:4.4.14' + container_name: project_mongo_1 + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + # volumes: + # - mongo-data:/data/db + # logging: + # driver: none + gotenberg: + image: gotenberg/gotenberg:latest + container_name: gotenberg + ports: + - '3003:3000' + networks: + - project_net + restart: 'always' + + # portal: + # image: shikshalokamqa/elevate-project-obervation-pwa:3.4.0.1 + # container_name: portal + # ports: + # - '7007:7007' + # volumes: + # - ./env.js:/usr/src/app/www/ml/assets/env/env.js + # networks: + # - project_net + +networks: + project_net: + external: false +#volumes: +# mongo-data: +# citus-data: diff --git a/documentation/3.4.0/dockerized/envs/entity_management_env b/documentation/3.4.0/dockerized/envs/entity_management_env new file mode 100644 index 00000000..8f530d17 --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/entity_management_env @@ -0,0 +1,23 @@ +APPLICATION_PORT = 5001 +APPLICATION_ENV ="development" +APPLICATION_BASE_URL='/entity-management/' +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +MONGODB_URL=mongodb://mongo:27017/elevate-entity +AUTH_METHOD = native +USER_SERVICE_URL = http://interface:3569 +USER_SERVICE_BASE_URL=/user +KAFKA_HEALTH_CHECK_TOPIC=test +SERVICE_NAME = elevate-entity-service +API_DOC_URL="https://entity-management/entity-management/api-doc" +APPLICATION_HOST=entity_management +IS_AUTH_TOKEN_BEARER="false" +ADMIN_ACCESS_TOKEN=rwwee3$123 +ADMIN_TOKEN_HEADER_NAME="admin-auth-token" +INTERFACE_SERVICE_URL=http://interface:3569 +KAFKA_HEALTH_CHECK_TOPIC = entity-health-check-topic-check +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_URL=kafka:9092 +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_GROUP_ID = entity +HEALTH_CHECK_DEBUG_MODE = true \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/envs/env.js b/documentation/3.4.0/dockerized/envs/env.js new file mode 100644 index 00000000..9606a60a --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/env.js @@ -0,0 +1,17 @@ +window['env'] = { + production: true, + baseURL: 'https://qa.elevate-apis.shikshalokam.org', + capabilities: 'all', + restrictedPages: ['DOWNLOADS', 'AUTH_PAGES', 'PROFILE', 'EDIT_PROFILE'], + unauthorizedRedirectUrl: '/', + isAuthBypassed: true, + profileRedirectPath: '', + showHeader: true, + config: { + logoPath: 'assets/images/logo.png', + faviconPath: 'assets/icons/elevate-logo.png', + title: 'Elevate', + redirectUrl: '/home', + }, + hostPath: '/ml/', +} diff --git a/documentation/3.4.0/dockerized/envs/interface_env b/documentation/3.4.0/dockerized/envs/interface_env new file mode 100644 index 00000000..7e3c6762 --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/interface_env @@ -0,0 +1,24 @@ +API_DOC_URL=/interface/api-doc +APPLICATION_ENV=development +APPLICATION_PORT=3569 +ELEVATE_NOTIFICATION_KAFKA_BROKERS=kafka:9092 +ELEVATE_NOTIFICATION_KAFKA_GROUP_ID=mentoring +ELEVATE_NOTIFICATION_KAFKA_TOPIC=notification +ENTITY_SERVICE_BASE_URL=http://entity_management:5001 +INSTALLED_PACKAGES=elevate-mentoring elevate-survey-observation@1.0.1 elevate-self-creation-portal +NOTIFICATION_SERVICE_BASE_URL=http://localhost:7201 +PROJECT_SERVICE_BASE_URL=http://project:6000 +RATE_LIMITER_ENABLED=true +RATE_LIMITER_GENERAL_LIMIT=500 +RATE_LIMITER_NUMBER_OF_PROXIES=3 +RATE_LIMITER_PUBLIC_LOW_LIMIT=5 +REQUIRED_BASE_PACKAGES=elevate-mentoring elevate-project elevate-survey-observation self-creation-portal +REQUIRED_PACKAGES=elevate-mentoring@1.2.90 elevate-survey-observation@1.0.22 elevate-project@1.1.53 shiksha-notification@1.1.3 elevate-self-creation-portal@1.0.70 +ROUTE_CONFIG_JSON_URLS_PATHS=https://raw.githubusercontent.com/ELEVATE-Project/utils/refs/heads/master/interface-routes/elevate-routes.json +SAAS_NOTIFICATION_BASE_URL=interface/v1/notification/send-raw +SAAS_NOTIFICATION_SEND_EMAIL_ROUTE=interface/v1/notification/send-raw +SAMIKSHA_SERVICE_BASE_URL=http://localhost:4301 +SCHEDULER_SERVICE_BASE_URL=http://localhost:7401 +SUPPORTED_HTTP_TYPES=GET POST PUT PATCH DELETE +SURVEY_SERVICE_BASE_URL=http://samiksha:4301 +USER_SERVICE_BASE_URL=http://user:3001 \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/envs/notification_env b/documentation/3.4.0/dockerized/envs/notification_env new file mode 100644 index 00000000..c821b118 --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/notification_env @@ -0,0 +1,12 @@ +# Database +POSTGRES_HOST=citus_master +POSTGRES_PORT=5432 +POSTGRES_DATABASE=notification +POSTGRES_USERNAME=postgres + +RABBITMQ_URL=amqp://rabbitmq:5672 + + +# Application +PORT=3002 +NODE_ENV=development \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/envs/project_env b/documentation/3.4.0/dockerized/envs/project_env new file mode 100644 index 00000000..65e7fe3d --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/project_env @@ -0,0 +1,51 @@ +APPLICATION_PORT = 6000 +APPLICATION_ENV = development +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +MONGODB_URL = mongodb://mongodb:27017/elevate-project +KEYCLOAK_PUBLIC_KEY_PATH = keycloak-public-keys +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_URL =kafka:9092 +KAFKA_GROUP_ID = projects +KAFKA_HEALTH_CHECK_TOPIC = project-health-check-topic-check +PROJECT_SUBMISSION_TOPIC=sl-improvement-project-submission-dev +SUBMISSION_TOPIC = Projectsubmissions +PROJECT_CERTIFICATE_TOPIC = generateProjectCertificate +ELEVATE_PROJECT_SERVICE_URL=http://project:6000 +SERVICE_NAME = project +USER_DELETE_TOPIC = deleteuser +TELEMETRY_TOPIC=telemetry.raw +ID = projectservice +TELEMETRY_ON_OFF=ON +USER_DELETE_ON_OFF=OFF +CLOUD_STORAGE=ON +TIMEZONE_DIFFRENECE_BETWEEN_LOCAL_TIME_AND_UTC = +05:30 +VALIDATE_ENTITIES = ON +APP_PORTAL_BASE_URL =http://portal:7007 +NO_OF_MINUTES = 30 +NO_OF_EXPIRY_TIME = 60 +PRESIGNED_URL_EXPIRY_IN_SECONDS = 300 +DOWNLOADABLE_URL_EXPIRY_IN_SECONDS = 300 +DEFAULT_ORGANISATION_CODE = 1 +GOTENBERG_URL=http://gotenberg:3000 +API_DOC_URL="http://project/project/api-doc" +INTERFACE_SERVICE_URL = http://interface:3569 +USER_SERVICE_BASE_URL = "/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL = "/entity-management" +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_ACCOUNTNAME=CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_SECRET="CLOUD_STORAGE_SECRET" +CLOUD_STORAGE_BUCKETNAME=CLOUD_STORAGE_BUCKETNAME +CLOUD_STORAGE_BUCKET_TYPE=private +ADMIN_ACCESS_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_AUTH_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_TOKEN_HEADER_NAME = 'admin-auth-token' +IS_AUTH_TOKEN_BEARER = false +AUTH_METHOD = native +REDIS_HOST=redis://redis:6379 +PUBLIC_ASSET_BUCKETNAME=mentoring-storage-public +USER_SERVICE_URL = http://user:3569 +RESOURCE_DELETION_TOPIC=RESOURCE_DELETION_TOPIC +CLOUD_STORAGE_PROJECT =sl-project +PROGRAM_USER_MAPPING_TOPIC=local.program +SESSION_VERIFICATION_METHOD=user_service_authenticated \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/envs/samiksha_env b/documentation/3.4.0/dockerized/envs/samiksha_env new file mode 100644 index 00000000..bbdf6e32 --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/samiksha_env @@ -0,0 +1,66 @@ +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +ADMIN_ACCESS_TOKEN=CN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_AUTH_TOKEN=CN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_TOKEN_HEADER_NAME=admin-auth-token +API_DOC_URL=/survey/api-doc +APPLICATION_BASE_URL=/survey/ +APP_PORTAL_BASE_URL=http://portal:7007 +APP_PORTAL_DIRECTORY=/observations/ +AUTH_CONFIG_FILE_PATH=config.json +AUTH_METHOD=native +CLOUD_STORAGE=GCP +CLOUD_STORAGE_ACCOUNTNAME=CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_BUCKETNAME=mentoring-dev-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +CLOUD_STORAGE_PROJECT=sl-dev-project +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_SECRET=----BEGIN PRIVATE KEY----- +COMPLETED_OBSERVATION_SUBMISSION_TOPIC=elevate_observations_dev +COMPLETED_SUBMISSION_TOPIC=elevate_submissions_dev +COMPLETED_SURVEY_SUBMISSION_TOPIC=elevate_surveys_raw_dev +CSV_REPORTS_PATH=reports +DB=elevate-samiksha +DEFAULT_ORGANISATION_CODE=default_code +ELEVATE_SURVEY_SERVICE_URL=http://samiksha:7007 +ENTITY_BASE_URL=http://interface:3569 +ENTITY_MANAGEMENT_SERVICE_URL=http://interface:3569/entity-management +GOTENBERG_URL=http://gotenberg:3000 +HOST=localhost +IMPROVEMENT_PROJECT_BASE_URL=http://project:3569 +IMPROVEMENT_PROJECT_SUBMISSION_TOPIC=elevate_project_task_submissions_dev +INCOMPLETE_OBSERVATION_SUBMISSION_TOPIC=elevate_observations_dev +INCOMPLETE_SUBMISSION_TOPIC=elevate_submissions_dev +INCOMPLETE_SURVEY_SUBMISSION_TOPIC=elevate_surveys_raw_dev +INTERFACE_SERVICE_URL=http://interface:3569 +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +IS_AUTH_TOKEN_BEARER=false +Instance=ELEVATE +KAFKA_COMMUNICATIONS_ON_OFF=ON +KAFKA_GROUP_ID=dev.survey +KAFKA_HEALTH_CHECK_TOPIC=survey-health-check-topic-check +KAFKA_URL=kafka:9092 +LOG=debug +MOBILE_APPLICATION_APP_TYPE=assessment +MONGODB_URL=mongodb://mongo:27017 +NODE_ENV=development +NOTIFICATIONS_TOPIC=elevate_notifications_dev +ORG_UPDATES_TOPIC=dev.organizationEvent +PORT=4301 +PROGRAM_USER_MAPPING_TOPIC=dev.program +PROJECT_SERVICE_NAME=/project +PUBLIC_FOLDER_PATH=public +REQUEST_TIMEOUT_FOR_REPORTS=600000 +SERVICE_NAME=survey +SERVICE_NAME_HEALTH_CHECK=SamikshaService +SUBMISSION_RATING_QUEUE_TOPIC=elevate_submissions_rating_dev +SUBMISSION_UPDATE_KAFKA_PUSH_ON_OFF=ON +TIMEZONE_DIFFRENECE_BETWEEN_LOCAL_TIME_AND_UTC=+05:30 +TOP_LEVEL_ENTITY_TYPE=state +USER_ACCOUNT_EVENT_TOPIC=dev.userCreate +USER_COURSES_SUBMISSION_TOPIC=elevate_user_courses_dev +USER_COURSES_TOPIC=elevate_user_courses_raw +USER_DELETE_ON_OFF=ON +USER_DELETE_TOPIC=dev.userCreate +USER_SERVICE_URL=http://interface:3569/user +VALIDATE_ENTITIES=ON +VALIDATE_ROLE=ON diff --git a/documentation/3.4.0/dockerized/envs/scheduler_env b/documentation/3.4.0/dockerized/envs/scheduler_env new file mode 100644 index 00000000..9de73d13 --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/scheduler_env @@ -0,0 +1,12 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/scheduler/ +APPLICATION_ENV=development +APPLICATION_PORT=4000 +DEFAULT_QUEUE=email +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +KAFKA_URL=kafka:9092 +NOTIFICATION_KAFKA_TOPIC=notifications +REDIS_HOST=redis +REDIS_PORT=6379 \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/envs/user_env b/documentation/3.4.0/dockerized/envs/user_env new file mode 100644 index 00000000..c72a1d2c --- /dev/null +++ b/documentation/3.4.0/dockerized/envs/user_env @@ -0,0 +1,99 @@ +ACCESS_TOKEN_EXPIRY='30m' +ALLOWED_HOST='*' +ACCESS_TOKEN_SECRET='bsj82AHBxahusub12yexlashsbxAXADHBlaj' +API_DOC_URL=/user/api-doc +APP_NAME=MentorED +APPLICATION_ENV=development +APPLICATION_PORT=3001 +CLOUD_STORAGE_PROVIDER=aws +CLOUD_STORAGE_BUCKETNAME=mentoring-prod-storage-private +CLOUD_STORAGE_SECRET=AKIAIOSFODNN7EXAMPLE +CLOUD_STORAGE_REGION=ap-south-1 +CLOUD_ENDPOINT=s3.ap-south-1.amazonaws.com +CLOUD_STORAGE_ACCOUNTNAME=mentoring-prod-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +PUBLIC_ASSET_BUCKETNAME=mentoring-prod-storage-private +AZURE_ACCOUNT_KEY='AZURE_ACCOUNT_KEY' +AZURE_ACCOUNT_NAME=elevatementoringaccount +CLEAR_INTERNAL_CACHE=userinternal +CLOUD_STORAGE=GCP +DEFAULT_AZURE_CONTAINER_NAME=mentoring-azure-private +DEFAULT_GCP_BUCKET_NAME=mentoring-dev-storage-private +ENABLE_EMAIL_OTP_VERIFICATION=false +ENABLE_LOG=true +GCP_PATH=gcp.json +GCP_PROJECT_ID=sl-dev-project +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +INTERNAL_CACHE_EXP_TIME=86400 +IV=LHYOA5YnTonqcgrm15k3/Q== +KAFKA_GROUP_ID=users +KAFKA_TOPIC=dev.topic.user +KAFKA_URL=kafka:9092 +KEY=E/m3RD/aM3Ed3lLfYVcKizakG9R+bFybAPZSLjIP2hY= +MENTOR_SECRET_CODE=4567 +MONGODB_URL=mongodb://mongo:27017/elevate-users +NOTIFICATION_KAFKA_TOPIC=dev.notifications +OTP_EMAIL_TEMPLATE_CODE=emailotp +OTP_EXP_TIME=86400 +RATING_KAFKA_TOPIC=dev.mentor_rating +REDIS_HOST=redis://redis:6379 +REFRESH_TOKEN_EXPIRY=183 +REFRESH_TOKEN_SECRET=371hkjkjady2y3ihdkajshdkiq23iuekw71yekhaskdvkvegavy23t78veqwexqvxveit6ttxyeeytt62tx236vv +REGISTRATION_EMAIL_TEMPLATE_CODE=registration +REGISTRATION_OTP_EMAIL_TEMPLATE_CODE=registrationotp +SALT_ROUNDS=10 +DEFAULT_OCI_BUCKET_NAME=mentoring-oci-private +OCI_ACCESS_KEY_ID=81a4c2553026982360af6b24497c489b0fea9436 +OCI_BUCKET_ENDPOINT=https://axgqmpkrpmt5.compat.objectstorage.ap-hyderabad-1.oraclecloud.com +OCI_BUCKET_REGION=ap-hyderabad-1 +OCI_SECRET_ACCESS_KEY='+U4O+CjiC6M/mOcGjYh7K/9XjfSdJ79OoLuQrABPOJ8=' +ERROR_LOG_LEVEL=silly +DISABLE_LOG=false +DEFAULT_ORGANISATION_CODE=default_code +DEV_DATABASE_URL=postgres://postgres:postgres@citus_master:5432/user +ADMIN_SECRET_CODE=W5bF7gesuS0xsNWmpsKy +MENTORING_SERVICE_URL="http://mentoring:3000" +INVITEE_EMAIL_TEMPLATE_CODE="invite_user" +ADMIN_INVITEE_UPLOAD_EMAIL_TEMPLATE_CODE="invitee_upload_status" +DEFAULT_QUEUE="defaultque" +MENTOR_INVITATION_EMAIL_TEMPLATE_CODE="invite_mentor" +MENTEE_INVITATION_EMAIL_TEMPLATE_CODE="invite_mentee" +DEFAULT_ROLE="mentee" +SAMPLE_CSV_FILE_PATH="sample/bulk_user_creation.csv" +ORG_ADMIN_INVITATION_EMAIL_TEMPLATE_CODE="invite_org_admin" +DEFAULT_ORG_ID=1 +PORTAL_URL="portaladdress" +SCHEDULER_SERVICE_HOST="http://scheduler:4000" +SCHEDULER_SERVICE_BASE_URL="/scheduler/" +REFRESH_VIEW_INTERVAL=100000 +EMAIL_ID_ENCRYPTION_IV='a390328e496f025249a88384f318a536' +EMAIL_ID_ENCRYPTION_KEY='9bbf4698e081176b4e38c3f04f9c0cff6ae80b1960e5ac868cc234ac8537aa66' +EMAIL_ID_ENCRYPTION_ALGORITHM='aes-256-cbc' +GENERIC_INVITATION_EMAIL_TEMPLATE_CODE='check_code' +EVENT_ORG_LISTENER_URLS="http://interface:3569/mentoring/v1/organization/eventListener" +EVENT_ENABLE_ORG_EVENTS=false +DOWNLOAD_URL_EXPIRATION_DURATION=300 +APPLICATION_HOST="user" +CHANGE_PASSWORD_TEMPLATE_CODE="change_password" +CAPTCHA_ENABLE=false +RECAPTCHA_SECRET_KEY="6LfWEKYpAAAAAJS0eukS2Su_5vwlXRs5vPbC34W0" +ALLOWED_IDLE_TIME=1200000 +APPLICATION_BASE_URL="/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL="http://interface:3569/entity-management/" +IS_AUTH_TOKEN_BEARER=false +DEFAULT_TENANT_ORG_CODE=default_code +DEFAULT_TENANT_ORG_NAME="Default Organization" +EVENT_ENABLE_ORG_KAFKA_EVENTS=true +EVENT_ENABLE_TENANT_KAFKA_EVENTS=true +EVENT_ENABLE_USER_KAFKA_EVENTS=true +EVENT_ORGANIZATION_KAFKA_TOPIC="dev.organizationEvent" +EVENT_TENANT_KAFKA_TOPIC="dev.tenantEvent" +EVENT_USER_KAFKA_TOPIC="dev.userCreate" +INTERFACE_SERVICE_HOST="http://interface:3569" +JWT_SECRET='bsj82AHBxahusub12yexlashsbxAXADHBlaj' +SCHEDULER_SERVICE_ERROR_REPORTING_EMAIL_ID="test@yopmail.com" +SCHEDULER_SERVICE_URL="http://interface:3569/jobs/scheduleJob" +SERVICE_NAME="UserService" +SIGNED_URL_EXPIRY_IN_SECONDS="900" +ORG_CODE_HEADER_NAME=organization-id +ORG_ID_HEADER_NAME=organization-id diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-down.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-down.sh new file mode 100644 index 00000000..921fed2b --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-down.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" +export samiksha_env="$SCRIPT_DIR/samiksha_env" + + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" down \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-up.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-up.sh new file mode 100644 index 00000000..6aa48422 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-up.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" +export samiksha_env="$SCRIPT_DIR/samiksha_env" + + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" up diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/insert_sample_data.sql b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/insert_sample_data.sql new file mode 100644 index 00000000..38991895 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/insert_sample_data.sql @@ -0,0 +1,116 @@ +-- ================================ +-- USERS +-- ================================ +INSERT INTO public.users +(id, name, email, email_verified, roles, status, password, + has_accepted_terms_and_conditions, about, location, languages, + preferred_language, share_link, image, custom_entity_text, meta, + created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) +VALUES +(1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL); + +-- ================================ +-- USER ORGANIZATIONS +-- ================================ +INSERT INTO public.user_organizations +(user_id, organization_code, tenant_code, created_at, updated_at, deleted_at) +VALUES +(1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + +-- ================================ +-- USER ORGANIZATION ROLES +-- ================================ +INSERT INTO public.user_organization_roles +(tenant_code, user_id, organization_code, role_id, created_at, updated_at, deleted_at) +VALUES +('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 3, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 2, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 4, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + +-- ================================ +-- TENANT UPDATE +-- ================================ +UPDATE public.tenants +SET meta = '{ + "factors": ["professional_role", "professional_subroles"], + "observableEntityKeys": ["professional_subroles"], + "optional_factors": ["state", "district", "block", "cluster", "school"], + "validationExcludedScopeKeys": ["language", "gender"], + "portalSignInUrl": "https://shikshagrah-qa.tekdinext.com/register" +}' +WHERE code = 'default'; + +-- ================================ +-- ENTITY TYPES +-- ================================ +INSERT INTO public.entity_types +(id, value, label, status, created_by, updated_by, allow_filtering, + data_type, organization_id, parent_id, has_entities, allow_custom_entities, + model_names, created_at, updated_at, deleted_at, meta, + external_entity_type, required, regex, tenant_code, organization_code) +VALUES +(5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(10, 'professional_role', 'Professional Role', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(11, 'professional_subroles', 'Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'); + +-- ================================ +-- SEQUENCES +-- ================================ +SELECT setval('users_id_seq', (SELECT MAX(id) FROM public.users)); \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/setup_project.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/setup_project.sh new file mode 100644 index 00000000..8f3d5af2 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/setup_project.sh @@ -0,0 +1,128 @@ +#!/bin/bash +set -e + +# ----------------------------- +# Logging function +# ----------------------------- +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a setup_log.txt +} + +# ----------------------------- +# Step 0: Install Homebrew, Node.js, MongoDB +# ----------------------------- +log "Installing Homebrew (if missing)..." +if ! command -v brew >/dev/null 2>&1; then + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +fi + +log "Installing Node.js..." +brew install node || true + +log "Installing MongoDB Community 7.0..." +brew tap mongodb/brew || true +brew install mongodb-community@7.0 || true +log "Node.js and MongoDB installation completed." + +# ----------------------------- +# Step 1: Check Docker availability +# ----------------------------- +log "Checking Docker availability..." +if ! command -v docker >/dev/null 2>&1; then + echo "โŒ Docker is not installed. Install Docker Desktop for Mac first." + exit 1 +fi + +if ! docker info >/dev/null 2>&1; then + echo "โŒ Docker is not running. Please start Docker Desktop." + exit 1 +fi +log "Docker is installed and running." + +# ----------------------------- +# Step 2: Download Docker Compose file +# ----------------------------- +log "Downloading Docker Compose file..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml +log "Docker Compose file downloaded." + +# ----------------------------- +# Step 3: Download environment files +# ----------------------------- +log "Downloading environment files..." +curl -L \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/samiksha_env +log "Environment files downloaded." + + +# ----------------------------- +# Step 5: docker-compose scripts (mac-safe) +# ----------------------------- +# Step 6: Download additional scripts +log "Downloading docker-compose scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-down.sh +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/docker-compose-up.sh +chmod +x docker-compose-down.sh +chmod +x docker-compose-up.sh +log "docker-compose scripts downloaded." + +# ---- SAFE patch (command only, filenames untouched) +sed -i '' 's/^docker-compose /docker compose /g' docker-compose-up.sh +sed -i '' 's/^docker-compose /docker compose /g' docker-compose-down.sh +log "docker-compose scripts patched safely." + +# ----------------------------- +# Step 6: SQL distribution file +# ----------------------------- +log "Downloading distributionColumns.sql..." +mkdir -p user && curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql +log "distributionColumns.sql downloaded." + +# ----------------------------- +# Step 7: Citus setup script +# ----------------------------- +log "Downloading citus_setup.sh..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/citus_setup.sh +chmod +x citus_setup.sh +log "citus_setup.sh downloaded." + +# ----------------------------- +# Step 8: Sample data scripts +# ----------------------------- +log "Downloading sample data scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/insert_sample_data.sql +log "sample data scripts downloaded." + +# ----------------------------- +# Step 9: Node dependencies (FIX) +# ----------------------------- +log "Installing Node dependencies..." +if [ ! -f package.json ]; then + npm init -y +fi +npm install mongodb +log "MongoDB Node driver installed." + +# ----------------------------- +# Step 10: config.json +# ----------------------------- +log "Downloading config.json..." +curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json +log "config.json downloaded." + +# ----------------------------- +# Step 11: Start services +# ----------------------------- +log "Starting services using docker compose..." +./docker-compose-up.sh +log "Docker services started successfully." \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/citus_setup.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/citus_setup.sh new file mode 100644 index 00000000..861094d4 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/citus_setup.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# Exit on error +set -e + +# Ensure correct number of arguments are provided +if [ $# -lt 2 ]; then + echo "Error: Folder name and database URL not provided. Usage: $0 " + exit 1 +fi + +# Use the provided folder name +FOLDER_NAME="$1" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." + exit 1 +fi + +# Use the provided database URL +DEV_DATABASE_URL="$2" + +# Extract database credentials and connection details using awk for portability +DB_USER=$(echo $DEV_DATABASE_URL | awk -F '[:@/]' '{print $4}') +DB_PASSWORD=$(echo $DEV_DATABASE_URL | awk -F '[:@/]' '{print $5}') +DB_HOST=$(echo $DEV_DATABASE_URL | awk -F '[:@/]' '{print $6}') +DB_PORT=$(echo $DEV_DATABASE_URL | awk -F '[:@/]' '{split($7,a,"/"); print a[1]}') +DB_NAME=$(echo $DEV_DATABASE_URL | awk -F '/' '{print $NF}') + +# Log database variables +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_PASSWORD: $DB_PASSWORD" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" + +# Define the container name (same as DB_HOST) +CONTAINER_NAME="$DB_HOST" + +# Wait for Docker container to be up +echo "Waiting for Docker container '$CONTAINER_NAME' to be up..." +while ! docker inspect "$CONTAINER_NAME" &>/dev/null; do + echo "Waiting for container..." + sleep 1 +done +echo "Container is now up." + +# Wait for PostgreSQL to be ready to accept connections +echo "Waiting for PostgreSQL on '$DB_HOST:$DB_PORT' to accept connections..." +until docker exec "$CONTAINER_NAME" bash -c "pg_isready -h localhost -p $DB_PORT -U $DB_USER"; do + echo "Waiting for database to be ready..." + sleep 1 +done +echo "Database is ready." + +# Function to check if the database exists +check_database() { + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -p $DB_PORT -lqt | cut -d \| -f 1 | grep -qw '$DB_NAME'" +} + +echo "Checking existence of database '$DB_NAME'..." +until check_database; do + echo "Database '$DB_NAME' does not exist, waiting..." + sleep 5 +done +echo "Database '$DB_NAME' exists, proceeding with script." + +# Retrieve and prepare SQL file operations +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." + exit 1 +fi +echo "Copying distributionColumns.sql to container '$CONTAINER_NAME'..." +docker cp "$DISTRIBUTION_COLUMNS_FILE" "$CONTAINER_NAME:/distributionColumns.sql" + +echo "Creating Citus extension in the database..." +docker exec --user "$DB_USER" "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -c 'CREATE EXTENSION IF NOT EXISTS citus;'" + +# Function to check if table exists +check_table() { + local table=$1 + local exists=$(docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -t -c \"SELECT EXISTS(SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = '$table');\"") + exists=$(echo "$exists" | tr -d '[:space:]') # Trim whitespace + echo "Debug: exists result for table $table = '$exists'" # Debug line + [[ "$exists" == "t" ]] # Checking specifically for 't' +} + +# Execute the SQL file with checks for table existence +echo "Creating distribution columns..." +while IFS= read -r line; do + if [[ $line =~ create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Checking existence of table '$table'..." + until check_table "$table"; do + echo "Table '$table' does not exist, waiting..." + sleep 1 + done + echo "Table '$table' exists, executing: $line" + docker exec --user "$DB_USER" "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -c \"$line\"" + fi +done <"$DISTRIBUTION_COLUMNS_FILE" + +echo "Citus extension setup complete." \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-down.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-down.sh new file mode 100644 index 00000000..921fed2b --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-down.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" +export samiksha_env="$SCRIPT_DIR/samiksha_env" + + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" down \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-up.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-up.sh new file mode 100644 index 00000000..6aa48422 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-up.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" +export samiksha_env="$SCRIPT_DIR/samiksha_env" + + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" up diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/insert_sample_data.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/insert_sample_data.sh new file mode 100755 index 00000000..59284c92 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/insert_sample_data.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" + +# --- 2. INSERT INTO public.user_organizations --- +# FIXES: +# - Quoted the organization_code and tenant_code variables. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + +# --- 3. INSERT INTO public.user_organization_roles --- +# FIXES: +# - Quoted the organization_code and tenant_code variables. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 3, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 4, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + + +psql -h localhost -p 5432 -U postgres -d user -c " +UPDATE public.tenants +SET meta = '{ + \"factors\": [\"professional_role\", \"professional_subroles\"], + \"observableEntityKeys\": [\"professional_subroles\"], + \"optional_factors\": [\"state\", \"district\", \"block\", \"cluster\", \"school\"], + \"validationExcludedScopeKeys\": [\"language\", \"gender\"], + \"portalSignInUrl\": \"https://shikshagrah-qa.tekdinext.com/register\" +}' +WHERE code = 'default'; +" + +# --- 4. INSERT INTO public.entity_types --- +# FIXES: +# - Quoted the JSON value for the 'meta' column. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (10, 'professional_role','Professional Role','ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (11, 'professional_subroles','Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" + +# --- 5. UPDATES and SEQUENCES --- +psql -h localhost -p 5432 -U postgres -d user -c "SELECT nextval('users_id_seq'::regclass) FROM public.users;" +psql -h localhost -p 5432 -U postgres -d user -c "SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials;" +psql -h localhost -p 5432 -U postgres -d user -c "SELECT NULL;" + + + diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/setup_project.sh b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/setup_project.sh new file mode 100644 index 00000000..8a7d9dde --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/setup_project.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Logging function +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> setup_log.txt +} + +# Step 1: Download Docker Compose file +log "Downloading Docker Compose file..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml +log "Docker Compose file downloaded." + +# Step 2: Download environment files +log "Downloading environment files..." +curl -L \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/samiksha_env +log "Environment files downloaded." + + +# Step 6: Download additional scripts +log "Downloading docker-compose scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-up.sh +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/docker-compose-down.sh +log "docker-compose scripts downloaded." + +# Step 7: Make the scripts executable +log "Making docker-compose scripts executable..." +chmod +x docker-compose-up.sh +chmod +x docker-compose-down.sh +log "Made docker-compose scripts executable." + +# Step 8: Create user directory and download SQL file +log "Creating user directory and downloading distributionColumns.sql..." +mkdir -p user && curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql +log "User directory created and distributionColumns.sql downloaded." + +# Step 9: Download and make citus_setup.sh executable +log "Downloading citus_setup.sh..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/citus_setup.sh +chmod +x citus_setup.sh + +# Install MongoDB driver (usually needed if connecting directly to MongoDB/Citus) +npm install mongodb + +# Install Mongoose (Object Data Modeling library, if the scripts use it) +npm install mongoose + +# Step 11: Download additional scripts to add data +log "Downloading sample data scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/insert_sample_data.sh +log "sample data scripts downloaded." + + +log "Downloading config.json file..." +curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json +log "config.json file is downloaded." + +# Step 13: Run docker-compose-up.sh script +log "Running docker-compose-up.sh script..." +./docker-compose-up.sh +log "docker-compose-up.sh script executed." diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/citus_setup.bat b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/citus_setup.bat new file mode 100644 index 00000000..61e3935d --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/citus_setup.bat @@ -0,0 +1,77 @@ +@echo off + +rem Exit on error +setlocal enabledelayedexpansion + +if "%~2"=="" ( + echo Error: Folder name and database URL not provided. Usage: %0 ^ ^ + exit /b 1 +) + +rem Use the provided folder name +set "FOLDER_NAME=%~1" + +rem Check if folder exists +if not exist "%FOLDER_NAME%\" ( + echo Error: Folder '%FOLDER_NAME%' not found. + exit /b 1 +) + +rem Use the provided database URL +set "DEV_DATABASE_URL=%~2" + +set "conn=%DEV_DATABASE_URL%" + +set "conn=!conn:postgres://=!" + +for /f "tokens=1 delims=:" %%a in ("!conn!") do set "DB_USER=%%a" + +set "conn=!conn:%DB_USER%:=!" + +for /f "tokens=1 delims=@" %%a in ("!conn!") do set "DB_PASSWORD=%%a" + +set "conn=!conn:%DB_PASSWORD%@=!" + +set "hostport=!conn:*@=!" +for /f "tokens=1 delims=:" %%a in ("!hostport!") do set "DB_HOST=%%a" + +set "conn=!conn:%DB_HOST%:=!" + +for /f "tokens=1 delims=/" %%a in ("!conn!") do set "DB_PORT=%%a" + +set "conn=!conn:*%DB_PORT%/=!" + +set "DB_NAME=!conn!" + +echo DB_USER: %DB_USER% +echo DB_PASSWORD: %DB_PASSWORD% +echo DB_HOST: %DB_HOST% +echo DB_PORT: %DB_PORT% +echo DB_NAME: %DB_NAME% + +rem Path to the script directory +for %%I in ("%~dp0") do set "SCRIPT_DIR=%%~fI" + +rem Path to distributionColumns.sql file +set "DISTRIBUTION_COLUMNS_FILE=%SCRIPT_DIR%\%FOLDER_NAME%\distributionColumns.sql" + +if not exist "%DISTRIBUTION_COLUMNS_FILE%" ( + echo Error: distributionColumns.sql file not found in folder '%FOLDER_NAME%'. + exit /b 1 +) + +rem Create Citus extension +echo Creating Citus extension in the database... +docker exec -i %DB_HOST% psql -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -c "CREATE EXTENSION IF NOT EXISTS citus;" + +rem Copy distributionColumns.sql file into the Docker container +echo Copying distributionColumns.sql file into the Docker container... +docker cp "%DISTRIBUTION_COLUMNS_FILE%" "%DB_HOST%:/tmp/distributionColumns.sql" + +rem Run distributionColumns.sql in the Docker container +echo Creating distribution columns... +docker exec -i %DB_HOST% psql -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -f "/tmp/distributionColumns.sql" + +echo Citus extension setup complete. + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-down.bat b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-down.bat new file mode 100644 index 00000000..30ea4f9b --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-down.bat @@ -0,0 +1,24 @@ +@echo off + +rem Set environment variables +set "users_env=%cd%\user_env" +set "interface_env=%cd%\interface_env" +set "scheduler_env=%cd%\scheduler_env" +set "notification_env=%cd%\notification_env" +set "project_env=%cd%\project_env" +set "samiksha_env=%cd%\samiksha_env" +set "entity_management_env=%cd%\entity_management_env" + +rem Run docker-compose +docker-compose -f docker-compose-project.yml down + +rem Optionally, clear environment variables after use +set "users_env=" +set "interface_env=" +set "scheduler_env=" +set "notification_env=" +set "project_env=" +set "samiksha_env=" +set "entity_management_env=" + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-up.bat b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-up.bat new file mode 100644 index 00000000..3ae24095 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-up.bat @@ -0,0 +1,24 @@ +@echo off + +rem Set environment variables +set "users_env=%cd%\user_env" +set "interface_env=%cd%\interface_env" +set "scheduler_env=%cd%\scheduler_env" +set "notification_env=%cd%\notification_env" +set "project_env=%cd%\project_env" +set "samiksha_env=%cd%\samiksha_env" +set "entity_management_env=%cd%\entity_management_env" + +rem Run docker-compose +docker-compose -f docker-compose-project.yml up + +rem Optionally, clear environment variables after use +set "users_env=" +set "interface_env=" +set "scheduler_env=" +set "notification_env=" +set "project_env=" +set "samiksha_env=" +set "entity_management_env=" + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_project_data.bat b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_project_data.bat new file mode 100644 index 00000000..f2a88e6a --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_project_data.bat @@ -0,0 +1,104 @@ +@echo off +SETLOCAL ENABLEDELAYEDEXPANSION + +echo ========================================== +echo Project Standalone Setup - Windows +echo ========================================== + +echo. +echo Downloading entity sample data files... +echo ------------------------------------------ + +curl -L -o entity_sampleData.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/entity_sampleData.js + +curl -L -o project_sampleData.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/project_sampleData.js + +curl -L -o survey_sampleData.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/survey_sampleData.js + +curl -L -o insert_sample_solutions.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/project-with-survey/insert_sample_solutions.js + +echo. +echo Files downloaded successfully. +echo. + +REM ------------------------------------------------ +REM Check and install Node.js +REM ------------------------------------------------ +echo Checking Node.js installation... +node -v >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo Node.js not found. Installing Node.js... + winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements +) ELSE ( + echo Node.js is already installed. +) + +REM ------------------------------------------------ +REM Check npm installation +REM ------------------------------------------------ +echo. +echo Checking npm installation... +npm -v >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo npm not found. Please reinstall Node.js. + pause + exit /b +) + +REM ------------------------------------------------ +REM Install mongodb npm package (REQUIRED CHANGE) +REM ------------------------------------------------ +echo. +echo Installing mongodb npm package... + +npm i mongodb + +IF ERRORLEVEL 1 ( + echo Failed to install mongodb npm package. + pause + exit /b +) ELSE ( + echo mongodb npm package installed successfully. +) + +REM ------------------------------------------------ +REM Check and install MongoDB Server +REM ------------------------------------------------ +echo. +echo Checking MongoDB installation... +mongod --version >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo MongoDB Server not found. Installing MongoDB Server... + winget install MongoDB.Server --accept-package-agreements --accept-source-agreements +) ELSE ( + echo MongoDB Server is already installed. +) + +REM ------------------------------------------------ +REM Check and install MongoDB Shell (mongosh) +REM ------------------------------------------------ +echo. +echo Checking MongoDB Shell (mongosh)... +mongosh --version >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo MongoDB Shell not found. Installing mongosh... + winget install MongoDB.Shell --accept-package-agreements --accept-source-agreements +) ELSE ( + echo MongoDB Shell is already installed. +) + +echo. +echo ========================================== +echo Setup completed successfully! +echo ========================================== + +pause +ENDLOCAL diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_sample_data.bat b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_sample_data.bat new file mode 100644 index 00000000..f1eefb27 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/insert_sample_data.bat @@ -0,0 +1,109 @@ +@echo off +setlocal enabledelayedexpansion + +:: Ensure the correct number of arguments are provided +if "%~2"=="" ( + echo Error: Folder name and database URL not provided. Usage: %0 <folder_name> <database_url> + exit /b 1 +) + +:: Use the provided folder name +set "FOLDER_NAME=sample-data\%~1" + +:: Check if folder exists +if not exist "%FOLDER_NAME%" ( + echo Error: Folder '%FOLDER_NAME%' not found. + exit /b 1 +) + +:: Use the provided database URL +set "DEV_DATABASE_URL=%~2" + +set "conn=%DEV_DATABASE_URL%" + +set "conn=!conn:postgres://=!" + +for /f "tokens=1 delims=:" %%a in ("!conn!") do set "DB_USER=%%a" + +set "conn=!conn:%DB_USER%:=!" + +for /f "tokens=1 delims=@" %%a in ("!conn!") do set "DB_PASSWORD=%%a" + +set "conn=!conn:%DB_PASSWORD%@=!" + +set "hostport=!conn:*@=!" +for /f "tokens=1 delims=:" %%a in ("!hostport!") do set "DB_HOST=%%a" + +set "conn=!conn:%DB_HOST%:=!" + +for /f "tokens=1 delims=/" %%a in ("!conn!") do set "DB_PORT=%%a" + +set "conn=!conn:*%DB_PORT%/=!" + +set "DB_NAME=!conn!" + +echo DB_USER: %DB_USER% +echo DB_PASSWORD: %DB_PASSWORD% +echo DB_HOST: %DB_HOST% +echo DB_PORT: %DB_PORT% +echo DB_NAME: %DB_NAME% + +:: Define the container name (same as DB_HOST) +set "CONTAINER_NAME=%DB_HOST%" + +:: Wait for Docker container to be up +echo Waiting for Docker container '%CONTAINER_NAME%' to be up... +:WAIT_CONTAINER +docker inspect "%CONTAINER_NAME%" >nul 2>&1 +if errorlevel 1 ( + echo Waiting for container... + timeout /t 1 /nobreak + goto WAIT_CONTAINER +) +echo Container is now up. + +:: Wait for PostgreSQL to be ready to accept connections +echo Waiting for PostgreSQL on '%DB_HOST%:%DB_PORT%' to accept connections... +:WAIT_DB +docker exec "%CONTAINER_NAME%" bash -c "pg_isready -h localhost -p %DB_PORT% -U %DB_USER%" >nul 2>&1 +if errorlevel 1 ( + echo Waiting for database to be ready... + timeout /t 1 /nobreak + goto WAIT_DB +) +echo Database is ready. + +:: Check if the database exists +:CHECK_DB +docker exec "%CONTAINER_NAME%" bash -c "PGPASSWORD='%DB_PASSWORD%' psql -h localhost -U %DB_USER% -p %DB_PORT% -lqt | cut -d \| -f 1 | grep -qw '%DB_NAME%'" >nul 2>&1 +if errorlevel 1 ( + echo Database '%DB_NAME%' does not exist, waiting... + timeout /t 5 /nobreak + goto CHECK_DB +) +echo Database '%DB_NAME%' exists, proceeding with script. + +:: Retrieve and prepare SQL file operations +set "SAMPLE_COLUMNS_FILE=%FOLDER_NAME%\sampleData.sql" +if not exist "%SAMPLE_COLUMNS_FILE%" ( + echo Error: sampleData.sql not found in folder '%FOLDER_NAME%'. + exit /b 1 +) + +:: Copy the SQL file into the Docker container +echo Copying sampleData.sql to container '%CONTAINER_NAME%'... +docker cp "%SAMPLE_COLUMNS_FILE%" "%CONTAINER_NAME%:/sampleData.sql" + +:: Execute the SQL file inside the container +echo Executing sampleData.sql in the database... +docker exec "%CONTAINER_NAME%" bash -c "PGPASSWORD='%DB_PASSWORD%' psql -h localhost -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -f /sampleData.sql" +if errorlevel 1 ( + echo Error executing SQL script. + exit /b 1 +) else ( + echo SQL script executed successfully. +) + +echo Sample Data Insertion Completed + +endlocal \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/sampleData.sql b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/sampleData.sql new file mode 100644 index 00000000..bd66c81c --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/sampleData.sql @@ -0,0 +1,111 @@ +BEGIN; + +-- ---------------- USERS ---------------- +INSERT INTO public.users ( + id, name, email, email_verified, roles, status, password, + has_accepted_terms_and_conditions, about, location, languages, + preferred_language, share_link, image, custom_entity_text, meta, + created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs +) VALUES +(1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL); + +-- ---------------- USER ORGANIZATIONS ---------------- +INSERT INTO public.user_organizations +(user_id, organization_code, tenant_code, created_at, updated_at, deleted_at) +VALUES +(1, 'default_code', 'default', now(), now(), NULL), +(2, 'default_code', 'default', now(), now(), NULL), +(3, 'default_code', 'default', now(), now(), NULL), +(4, 'default_code', 'default', now(), now(), NULL); + +-- ---------------- USER ORG ROLES ---------------- +INSERT INTO public.user_organization_roles +(tenant_code, user_id, organization_code, role_id, created_at, updated_at, deleted_at) +VALUES +('default', 2, 'default_code', 1, now(), now(), NULL), +('default', 3, 'default_code', 8, now(), now(), NULL), +('default', 2, 'default_code', 8, now(), now(), NULL), +('default', 4, 'default_code', 8, now(), now(), NULL); + +-- ---------------- TENANT META ---------------- +UPDATE public.tenants +SET meta = '{ + "factors": ["professional_role", "professional_subroles"], + "observableEntityKeys": ["professional_subroles"], + "optional_factors": ["state", "district", "block", "cluster", "school"], + "validationExcludedScopeKeys": ["language", "gender"], + "portalSignInUrl": "https://shikshagrah-qa.tekdinext.com/register" +}' +WHERE code = 'default'; + +-- ---------------- ENTITY TYPES ---------------- +INSERT INTO public.entity_types ( + id, value, label, status, created_by, updated_by, + allow_filtering, data_type, organization_id, parent_id, + has_entities, allow_custom_entities, model_names, + created_at, updated_at, deleted_at, + meta, external_entity_type, required, regex, + tenant_code, organization_code +) VALUES +(5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(10, 'professional_role', 'Professional Role', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(11, 'professional_subroles', 'Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'); + +-- ---------------- SEQUENCE FIX ---------------- +SELECT setval('users_id_seq', (SELECT MAX(id) FROM public.users)); +SELECT setval('entity_types_id_seq', (SELECT MAX(id) FROM public.entity_types)); + +COMMIT; diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-down.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-down.sh new file mode 100644 index 00000000..e26ce422 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-down.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" down \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-up.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-up.sh new file mode 100644 index 00000000..6866ee9c --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-up.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" + +# Run docker compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" up diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/insert_sample_data.sql b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/insert_sample_data.sql new file mode 100644 index 00000000..1f16c579 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/insert_sample_data.sql @@ -0,0 +1,116 @@ +-- ================================ +-- USERS +-- ================================ +INSERT INTO public.users +(id, name, email, email_verified, roles, status, password, + has_accepted_terms_and_conditions, about, location, languages, + preferred_language, share_link, image, custom_entity_text, meta, + created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) +VALUES +(1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL), + +(4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, + NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', + NULL, 'default', NULL, NULL, NULL); + +-- ================================ +-- USER ORGANIZATIONS +-- ================================ +INSERT INTO public.user_organizations +(user_id, organization_code, tenant_code, created_at, updated_at, deleted_at) +VALUES +(1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +(4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + +-- ================================ +-- USER ORGANIZATION ROLES +-- ================================ +INSERT INTO public.user_organization_roles +(tenant_code, user_id, organization_code, role_id, created_at, updated_at, deleted_at) +VALUES +('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 3, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 2, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL), +('default', 4, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + +-- ================================ +-- TENANT UPDATE +-- ================================ +UPDATE public.tenants +SET meta = '{ + "factors": ["professional_role", "professional_subroles"], + "observableEntityKeys": ["professional_subroles"], + "optional_factors": ["state", "district", "block", "cluster", "school"], + "validationExcludedScopeKeys": ["language", "gender"], + "portalSignInUrl": "https://shikshagrah-qa.tekdinext.com/register" +}' +WHERE code = 'default'; + +-- ================================ +-- ENTITY TYPES +-- ================================ +INSERT INTO public.entity_types +(id, value, label, status, created_by, updated_by, allow_filtering, + data_type, organization_id, parent_id, has_entities, allow_custom_entities, + model_names, created_at, updated_at, deleted_at, meta, + external_entity_type, required, regex, tenant_code, organization_code) +VALUES +(5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(10, 'professional_role', 'Professional Role', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(11, 'professional_subroles', 'Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, + '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', + NULL, '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'); + +-- ================================ +-- SEQUENCES +-- ================================ +SELECT setval('users_id_seq', (SELECT MAX(id) FROM public.users)); diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/setup_project.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/setup_project.sh new file mode 100644 index 00000000..c487609f --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/setup_project.sh @@ -0,0 +1,128 @@ +#!/bin/bash +set -e + +# ----------------------------- +# Logging function +# ----------------------------- +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a setup_log.txt +} + +# ----------------------------- +# Step 0: Install Homebrew, Node.js, MongoDB +# ----------------------------- +log "Installing Homebrew (if missing)..." +if ! command -v brew >/dev/null 2>&1; then + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +fi + +log "Installing Node.js..." +brew install node || true + +log "Installing MongoDB Community 7.0..." +brew tap mongodb/brew || true +brew install mongodb-community@7.0 || true +log "Node.js and MongoDB installation completed." + +# ----------------------------- +# Step 1: Check Docker availability +# ----------------------------- +log "Checking Docker availability..." +if ! command -v docker >/dev/null 2>&1; then + echo "โŒ Docker is not installed. Install Docker Desktop for Mac first." + exit 1 +fi + +if ! docker info >/dev/null 2>&1; then + echo "โŒ Docker is not running. Please start Docker Desktop." + exit 1 +fi +log "Docker is installed and running." + +# ----------------------------- +# Step 2: Download Docker Compose file +# ----------------------------- +log "Downloading Docker Compose file..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml +log "Docker Compose file downloaded." + +# ----------------------------- +# Step 3: Download environment files +# ----------------------------- +log "Downloading environment files..." +curl -L \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env +log "Environment files downloaded." + + +# ----------------------------- +# Step 5: docker-compose scripts (mac-safe) +# ----------------------------- +log "Downloading docker-compose scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-up.sh +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/docker-compose-down.sh +chmod +x docker-compose-down.sh +chmod +x docker-compose-up.sh + +chmod +x docker-compose-up.sh docker-compose-down.sh + +# ---- SAFE patch (command only, filenames untouched) +sed -i '' 's/^docker-compose /docker compose /g' docker-compose-up.sh +sed -i '' 's/^docker-compose /docker compose /g' docker-compose-down.sh +log "docker-compose scripts patched safely." + +# ----------------------------- +# Step 6: SQL distribution file +# ----------------------------- +log "Downloading distributionColumns.sql..." +mkdir -p user +curl -o ./user/distributionColumns.sql -JL \ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql +log "distributionColumns.sql downloaded." + +# ----------------------------- +# Step 7: Citus setup script +# ----------------------------- +log "Downloading citus_setup.sh..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/citus_setup.sh +chmod +x citus_setup.sh +log "citus_setup.sh downloaded." + +# ----------------------------- +# Step 8: Sample data scripts +# ----------------------------- +log "Downloading sample data scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/insert_sample_data.sql +log "Sample data scripts downloaded." + +# ----------------------------- +# Step 9: Node dependencies (FIX) +# ----------------------------- +log "Installing Node dependencies..." +if [ ! -f package.json ]; then + npm init -y +fi +npm install mongodb +log "MongoDB Node driver installed." + +# ----------------------------- +# Step 10: config.json +# ----------------------------- +log "Downloading config.json..." +curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json +log "config.json downloaded." + +# ----------------------------- +# Step 11: Start services +# ----------------------------- +log "Starting services using docker compose..." +./docker-compose-up.sh +log "Docker services started successfully." diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/citus_setup.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/citus_setup.sh new file mode 100644 index 00000000..34066c39 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/citus_setup.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +# --- 1. ARGUMENT VALIDATION --- +if [ $# -lt 2 ]; then + echo "Error: Folder name and database URL not provided." >&2 + echo "Usage: $0 " >&2 + exit 1 +fi + +# Use the provided folder name +FOLDER_NAME="$1" +DEV_DATABASE_URL="$2" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." >&2 + exit 1 +fi + +# --- 2. HIGHLY RELIABLE DATABASE URL PARSING --- +echo "Parsing database URL..." + +# Remove the protocol part (e.g., 'postgres://') +DB_CLEAN_URL=$(echo "$DEV_DATABASE_URL" | sed 's/.*:\/\///') + +# 1. Extract DB_NAME (last part after the final slash) +DB_NAME=$(echo "$DB_CLEAN_URL" | awk -F '/' '{print $NF}') +# 2. Extract HOST and PORT (remove DB_NAME and the preceding slash) +HOST_PORT_PATH=$(echo "$DB_CLEAN_URL" | sed "s/\/$DB_NAME//") + +# 3. Use standard ':' and '@' delimiters on the remaining string +DB_USER=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $1}') +DB_PASSWORD=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $2}') +DB_HOST=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $3}') +DB_PORT=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $4}') + +# Define the container name (assumes container name is the DB_HOST, which is 'citus_master') +CONTAINER_NAME="$DB_HOST" + +# Log database variables (excluding password) +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "" + +# Check the extracted port +if [[ -z "$DB_PORT" ]]; then + echo "Error: Could not extract database port. Check URL format." >&2 + exit 1 +fi + +# --- 3. WAIT FOR CONTAINER AND DATABASE --- + +# Wait for Docker container to be up +echo "Waiting for Docker container '$CONTAINER_NAME' to be up..." +until docker inspect "$CONTAINER_NAME" &>/dev/null; do + echo -n "." + sleep 1 +done +echo -e "\nContainer is now up." + +# Wait for PostgreSQL to be ready to accept connections +# Use DB_USER for the check, as it must be a valid user +echo "Waiting for PostgreSQL on '$DB_HOST:$DB_PORT' to accept connections..." +until docker exec "$CONTAINER_NAME" bash -c "pg_isready -h localhost -p $DB_PORT -U $DB_USER > /dev/null 2>&1"; do + echo -n "." + sleep 1 +done +echo -e "\nDatabase server is ready." + +# Check and wait for the target database to exist +echo "Checking existence of database '$DB_NAME'..." +until docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d postgres -p $DB_PORT -lqt | grep -qw '$DB_NAME'"; do + echo -n "." + sleep 5 +done +echo -e "\nDatabase '$DB_NAME' exists, proceeding with script." + +# --- 4. CITUS EXTENSION SETUP --- + +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." >&2 + exit 1 +fi + +echo "Copying distributionColumns.sql to container '$CONTAINER_NAME'..." +CONTAINER_SQL_PATH="/tmp/distributionColumns.sql" +docker cp "$DISTRIBUTION_COLUMNS_FILE" "$CONTAINER_NAME:$CONTAINER_SQL_PATH" + +echo "Creating Citus extension in the database..." +docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c 'CREATE EXTENSION IF NOT EXISTS citus;'" + +# --- 5. EXECUTE SQL FILE WITH ROBUST TABLE CHECK --- + +check_table() { + local table_name=$1 + # Check if we can select from the table. If we can't, it returns non-zero. + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT -q -t --set ON_ERROR_STOP=1 -c \"SELECT 1 FROM $table_name LIMIT 1;\"" > /dev/null 2>&1 +} + +echo "Starting creation of distributed tables..." +docker exec "$CONTAINER_NAME" bash -c "cat $CONTAINER_SQL_PATH" | while IFS= read -r line; do + trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + if [[ "$trimmed_line" =~ ^create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Processing table: '$table'" + + # Robust wait loop for the table to be created by the preceding process (e.g., migration) + until check_table "$table"; do + echo "Table '$table' does not exist yet (waiting for migration to finish)..." + sleep 1 + done + + echo "Table '$table' exists. Executing Citus distribution command..." + docker exec "$CONTAINER_NAME" bash -c "PGPASSWORD='$DB_PASSWORD' psql -h localhost -U $DB_USER -d $DB_NAME -p $DB_PORT --set ON_ERROR_STOP=1 -c \"$trimmed_line\"" + fi +done + +# Clean up temporary file in the container +docker exec "$CONTAINER_NAME" rm "$CONTAINER_SQL_PATH" + +echo "โœ… Citus extension setup and distribution columns complete successfully!" \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-down.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-down.sh new file mode 100644 index 00000000..e26ce422 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-down.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" down \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-up.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-up.sh new file mode 100644 index 00000000..bbab6136 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-up.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Get the directory of the shell script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Set environment variables +export notification_env="$SCRIPT_DIR/notification_env" +export scheduler_env="$SCRIPT_DIR/scheduler_env" +export project_env="$SCRIPT_DIR/project_env" +export users_env="$SCRIPT_DIR/user_env" +export interface_env="$SCRIPT_DIR/interface_env" +export entity_management_env="$SCRIPT_DIR/entity_management_env" + +# Run docker-compose +docker compose -f "$SCRIPT_DIR/docker-compose-project.yml" up diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/insert_sample_data.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/insert_sample_data.sh new file mode 100755 index 00000000..59284c92 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/insert_sample_data.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" + +# --- 2. INSERT INTO public.user_organizations --- +# FIXES: +# - Quoted the organization_code and tenant_code variables. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + +# --- 3. INSERT INTO public.user_organization_roles --- +# FIXES: +# - Quoted the organization_code and tenant_code variables. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 3, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 4, 'default_code', 8, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + + +psql -h localhost -p 5432 -U postgres -d user -c " +UPDATE public.tenants +SET meta = '{ + \"factors\": [\"professional_role\", \"professional_subroles\"], + \"observableEntityKeys\": [\"professional_subroles\"], + \"optional_factors\": [\"state\", \"district\", \"block\", \"cluster\", \"school\"], + \"validationExcludedScopeKeys\": [\"language\", \"gender\"], + \"portalSignInUrl\": \"https://shikshagrah-qa.tekdinext.com/register\" +}' +WHERE code = 'default'; +" + +# --- 4. INSERT INTO public.entity_types --- +# FIXES: +# - Quoted the JSON value for the 'meta' column. +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (10, 'professional_role','Professional Role','ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +psql -h localhost -p 5432 -U postgres -d user -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (11, 'professional_subroles','Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" + +# --- 5. UPDATES and SEQUENCES --- +psql -h localhost -p 5432 -U postgres -d user -c "SELECT nextval('users_id_seq'::regclass) FROM public.users;" +psql -h localhost -p 5432 -U postgres -d user -c "SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials;" +psql -h localhost -p 5432 -U postgres -d user -c "SELECT NULL;" + + + diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/setup_project.sh b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/setup_project.sh new file mode 100644 index 00000000..1961d19c --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/setup_project.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Logging function +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> setup_log.txt +} + +# Step 1: Download Docker Compose file +log "Downloading Docker Compose file..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml +log "Docker Compose file downloaded." + +# Step 2: Download environment files +log "Downloading environment files..." +curl -L \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env \ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env +log "Environment files downloaded." + + +# Step 6: Download additional scripts +log "Downloading docker-compose scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-up.sh +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/docker-compose-down.sh +log "docker-compose scripts downloaded." + +# Step 7: Make the scripts executable +log "Making docker-compose scripts executable..." +chmod +x docker-compose-up.sh +chmod +x docker-compose-down.sh +log "Made docker-compose scripts executable." + +# Step 8: Create user directory and download SQL file +log "Creating user directory and downloading distributionColumns.sql..." +mkdir -p user && curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql +log "User directory created and distributionColumns.sql downloaded." + +# Step 9: Download and make citus_setup.sh executable +log "Downloading citus_setup.sh..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/citus_setup.sh +chmod +x citus_setup.sh + +# Install MongoDB driver (usually needed if connecting directly to MongoDB/Citus) +npm install mongodb + +# Install Mongoose (Object Data Modeling library, if the scripts use it) +npm install mongoose + +# Step 11: Download additional scripts to add data +log "Downloading sample data scripts..." +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js +curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/insert_sample_data.sh +log "sample data scripts downloaded." + + +log "Downloading config.json file..." +curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json +log "config.json file is downloaded." + +# Step 13: Run docker-compose-up.sh script +log "Running docker-compose-up.sh script..." +./docker-compose-up.sh +log "docker-compose-up.sh script executed." diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/citus_setup.bat b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/citus_setup.bat new file mode 100644 index 00000000..61e3935d --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/citus_setup.bat @@ -0,0 +1,77 @@ +@echo off + +rem Exit on error +setlocal enabledelayedexpansion + +if "%~2"=="" ( + echo Error: Folder name and database URL not provided. Usage: %0 ^ ^ + exit /b 1 +) + +rem Use the provided folder name +set "FOLDER_NAME=%~1" + +rem Check if folder exists +if not exist "%FOLDER_NAME%\" ( + echo Error: Folder '%FOLDER_NAME%' not found. + exit /b 1 +) + +rem Use the provided database URL +set "DEV_DATABASE_URL=%~2" + +set "conn=%DEV_DATABASE_URL%" + +set "conn=!conn:postgres://=!" + +for /f "tokens=1 delims=:" %%a in ("!conn!") do set "DB_USER=%%a" + +set "conn=!conn:%DB_USER%:=!" + +for /f "tokens=1 delims=@" %%a in ("!conn!") do set "DB_PASSWORD=%%a" + +set "conn=!conn:%DB_PASSWORD%@=!" + +set "hostport=!conn:*@=!" +for /f "tokens=1 delims=:" %%a in ("!hostport!") do set "DB_HOST=%%a" + +set "conn=!conn:%DB_HOST%:=!" + +for /f "tokens=1 delims=/" %%a in ("!conn!") do set "DB_PORT=%%a" + +set "conn=!conn:*%DB_PORT%/=!" + +set "DB_NAME=!conn!" + +echo DB_USER: %DB_USER% +echo DB_PASSWORD: %DB_PASSWORD% +echo DB_HOST: %DB_HOST% +echo DB_PORT: %DB_PORT% +echo DB_NAME: %DB_NAME% + +rem Path to the script directory +for %%I in ("%~dp0") do set "SCRIPT_DIR=%%~fI" + +rem Path to distributionColumns.sql file +set "DISTRIBUTION_COLUMNS_FILE=%SCRIPT_DIR%\%FOLDER_NAME%\distributionColumns.sql" + +if not exist "%DISTRIBUTION_COLUMNS_FILE%" ( + echo Error: distributionColumns.sql file not found in folder '%FOLDER_NAME%'. + exit /b 1 +) + +rem Create Citus extension +echo Creating Citus extension in the database... +docker exec -i %DB_HOST% psql -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -c "CREATE EXTENSION IF NOT EXISTS citus;" + +rem Copy distributionColumns.sql file into the Docker container +echo Copying distributionColumns.sql file into the Docker container... +docker cp "%DISTRIBUTION_COLUMNS_FILE%" "%DB_HOST%:/tmp/distributionColumns.sql" + +rem Run distributionColumns.sql in the Docker container +echo Creating distribution columns... +docker exec -i %DB_HOST% psql -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -f "/tmp/distributionColumns.sql" + +echo Citus extension setup complete. + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-down.bat b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-down.bat new file mode 100644 index 00000000..83d15e8c --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-down.bat @@ -0,0 +1,22 @@ +@echo off + +rem Set environment variables +set "users_env=%cd%\user_env" +set "interface_env=%cd%\interface_env" +set "scheduler_env=%cd%\scheduler_env" +set "notification_env=%cd%\notification_env" +set "project_env=%cd%\project_env" +set "entity_management_env=%cd%\entity_management_env" + +rem Run docker-compose +docker-compose -f docker-compose-project.yml down + +rem Optionally, clear environment variables after use +set "users_env=" +set "interface_env=" +set "scheduler_env=" +set "notification_env=" +set "project_env=" +set "entity_management_env=" + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-up.bat b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-up.bat new file mode 100644 index 00000000..ee2917b9 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-up.bat @@ -0,0 +1,22 @@ +@echo off + +rem Set environment variables +set "users_env=%cd%\user_env" +set "interface_env=%cd%\interface_env" +set "scheduler_env=%cd%\scheduler_env" +set "notification_env=%cd%\notification_env" +set "project_env=%cd%\project_env" +set "entity_management_env=%cd%\entity_management_env" + +rem Run docker-compose +docker-compose -f docker-compose-project.yml up + +rem Optionally, clear environment variables after use +set "users_env=" +set "interface_env=" +set "scheduler_env=" +set "notification_env=" +set "project_env=" +set "entity_management_env=" + +pause \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_project_data.bat b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_project_data.bat new file mode 100644 index 00000000..9952925d --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_project_data.bat @@ -0,0 +1,101 @@ +@echo off +SETLOCAL ENABLEDELAYEDEXPANSION + +echo ========================================== +echo Project Standalone Setup - Windows +echo ========================================== + +echo. +echo Downloading entity sample data files... +echo ------------------------------------------ + +curl -L -o entity_sampleData.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/entity_sampleData.js + +curl -L -o project_sampleData.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/project_sampleData.js + +curl -L -o insert_sample_solutions.js ^ +https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/dockerized/stand-alone/insert_sample_solutions.js + +echo. +echo Files downloaded successfully. +echo. + +REM ------------------------------------------------ +REM Check and install Node.js +REM ------------------------------------------------ +echo Checking Node.js installation... +node -v >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo Node.js not found. Installing Node.js... + winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements +) ELSE ( + echo Node.js is already installed. +) + +REM ------------------------------------------------ +REM Check npm installation +REM ------------------------------------------------ +echo. +echo Checking npm installation... +npm -v >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo npm not found. Please reinstall Node.js. + pause + exit /b +) + +REM ------------------------------------------------ +REM Install mongodb npm package (AS REQUESTED) +REM ------------------------------------------------ +echo. +echo Installing mongodb npm package... + +npm i mongodb + +IF ERRORLEVEL 1 ( + echo Failed to install mongodb npm package. + pause + exit /b +) ELSE ( + echo mongodb npm package installed successfully. +) + +REM ------------------------------------------------ +REM Check and install MongoDB Server +REM ------------------------------------------------ +echo. +echo Checking MongoDB Server installation... +mongod --version >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo MongoDB Server not found. Installing MongoDB Server... + winget install MongoDB.Server --accept-package-agreements --accept-source-agreements +) ELSE ( + echo MongoDB Server is already installed. +) + +REM ------------------------------------------------ +REM Check and install MongoDB Shell (mongosh) +REM ------------------------------------------------ +echo. +echo Checking MongoDB Shell (mongosh)... +mongosh --version >nul 2>&1 + +IF ERRORLEVEL 1 ( + echo MongoDB Shell not found. Installing mongosh... + winget install MongoDB.Shell --accept-package-agreements --accept-source-agreements +) ELSE ( + echo MongoDB Shell is already installed. +) + +echo. +echo ========================================== +echo Setup completed successfully! +echo ========================================== + +pause +ENDLOCAL diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_sample_data.bat b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_sample_data.bat new file mode 100644 index 00000000..f1eefb27 --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_sample_data.bat @@ -0,0 +1,109 @@ +@echo off +setlocal enabledelayedexpansion + +:: Ensure the correct number of arguments are provided +if "%~2"=="" ( + echo Error: Folder name and database URL not provided. Usage: %0 <folder_name> <database_url> + exit /b 1 +) + +:: Use the provided folder name +set "FOLDER_NAME=sample-data\%~1" + +:: Check if folder exists +if not exist "%FOLDER_NAME%" ( + echo Error: Folder '%FOLDER_NAME%' not found. + exit /b 1 +) + +:: Use the provided database URL +set "DEV_DATABASE_URL=%~2" + +set "conn=%DEV_DATABASE_URL%" + +set "conn=!conn:postgres://=!" + +for /f "tokens=1 delims=:" %%a in ("!conn!") do set "DB_USER=%%a" + +set "conn=!conn:%DB_USER%:=!" + +for /f "tokens=1 delims=@" %%a in ("!conn!") do set "DB_PASSWORD=%%a" + +set "conn=!conn:%DB_PASSWORD%@=!" + +set "hostport=!conn:*@=!" +for /f "tokens=1 delims=:" %%a in ("!hostport!") do set "DB_HOST=%%a" + +set "conn=!conn:%DB_HOST%:=!" + +for /f "tokens=1 delims=/" %%a in ("!conn!") do set "DB_PORT=%%a" + +set "conn=!conn:*%DB_PORT%/=!" + +set "DB_NAME=!conn!" + +echo DB_USER: %DB_USER% +echo DB_PASSWORD: %DB_PASSWORD% +echo DB_HOST: %DB_HOST% +echo DB_PORT: %DB_PORT% +echo DB_NAME: %DB_NAME% + +:: Define the container name (same as DB_HOST) +set "CONTAINER_NAME=%DB_HOST%" + +:: Wait for Docker container to be up +echo Waiting for Docker container '%CONTAINER_NAME%' to be up... +:WAIT_CONTAINER +docker inspect "%CONTAINER_NAME%" >nul 2>&1 +if errorlevel 1 ( + echo Waiting for container... + timeout /t 1 /nobreak + goto WAIT_CONTAINER +) +echo Container is now up. + +:: Wait for PostgreSQL to be ready to accept connections +echo Waiting for PostgreSQL on '%DB_HOST%:%DB_PORT%' to accept connections... +:WAIT_DB +docker exec "%CONTAINER_NAME%" bash -c "pg_isready -h localhost -p %DB_PORT% -U %DB_USER%" >nul 2>&1 +if errorlevel 1 ( + echo Waiting for database to be ready... + timeout /t 1 /nobreak + goto WAIT_DB +) +echo Database is ready. + +:: Check if the database exists +:CHECK_DB +docker exec "%CONTAINER_NAME%" bash -c "PGPASSWORD='%DB_PASSWORD%' psql -h localhost -U %DB_USER% -p %DB_PORT% -lqt | cut -d \| -f 1 | grep -qw '%DB_NAME%'" >nul 2>&1 +if errorlevel 1 ( + echo Database '%DB_NAME%' does not exist, waiting... + timeout /t 5 /nobreak + goto CHECK_DB +) +echo Database '%DB_NAME%' exists, proceeding with script. + +:: Retrieve and prepare SQL file operations +set "SAMPLE_COLUMNS_FILE=%FOLDER_NAME%\sampleData.sql" +if not exist "%SAMPLE_COLUMNS_FILE%" ( + echo Error: sampleData.sql not found in folder '%FOLDER_NAME%'. + exit /b 1 +) + +:: Copy the SQL file into the Docker container +echo Copying sampleData.sql to container '%CONTAINER_NAME%'... +docker cp "%SAMPLE_COLUMNS_FILE%" "%CONTAINER_NAME%:/sampleData.sql" + +:: Execute the SQL file inside the container +echo Executing sampleData.sql in the database... +docker exec "%CONTAINER_NAME%" bash -c "PGPASSWORD='%DB_PASSWORD%' psql -h localhost -U %DB_USER% -d %DB_NAME% -p %DB_PORT% -f /sampleData.sql" +if errorlevel 1 ( + echo Error executing SQL script. + exit /b 1 +) else ( + echo SQL script executed successfully. +) + +echo Sample Data Insertion Completed + +endlocal \ No newline at end of file diff --git a/documentation/3.4.0/dockerized/scripts/stand-alone/windows/sampleData.sql b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/sampleData.sql new file mode 100644 index 00000000..bd66c81c --- /dev/null +++ b/documentation/3.4.0/dockerized/scripts/stand-alone/windows/sampleData.sql @@ -0,0 +1,111 @@ +BEGIN; + +-- ---------------- USERS ---------------- +INSERT INTO public.users ( + id, name, email, email_verified, roles, status, password, + has_accepted_terms_and_conditions, about, location, languages, + preferred_language, share_link, image, custom_entity_text, meta, + created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs +) VALUES +(1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL), + +(4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', + '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', + true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, + '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, + 'default', NULL, NULL, NULL); + +-- ---------------- USER ORGANIZATIONS ---------------- +INSERT INTO public.user_organizations +(user_id, organization_code, tenant_code, created_at, updated_at, deleted_at) +VALUES +(1, 'default_code', 'default', now(), now(), NULL), +(2, 'default_code', 'default', now(), now(), NULL), +(3, 'default_code', 'default', now(), now(), NULL), +(4, 'default_code', 'default', now(), now(), NULL); + +-- ---------------- USER ORG ROLES ---------------- +INSERT INTO public.user_organization_roles +(tenant_code, user_id, organization_code, role_id, created_at, updated_at, deleted_at) +VALUES +('default', 2, 'default_code', 1, now(), now(), NULL), +('default', 3, 'default_code', 8, now(), now(), NULL), +('default', 2, 'default_code', 8, now(), now(), NULL), +('default', 4, 'default_code', 8, now(), now(), NULL); + +-- ---------------- TENANT META ---------------- +UPDATE public.tenants +SET meta = '{ + "factors": ["professional_role", "professional_subroles"], + "observableEntityKeys": ["professional_subroles"], + "optional_factors": ["state", "district", "block", "cluster", "school"], + "validationExcludedScopeKeys": ["language", "gender"], + "portalSignInUrl": "https://shikshagrah-qa.tekdinext.com/register" +}' +WHERE code = 'default'; + +-- ---------------- ENTITY TYPES ---------------- +INSERT INTO public.entity_types ( + id, value, label, status, created_by, updated_by, + allow_filtering, data_type, organization_id, parent_id, + has_entities, allow_custom_entities, model_names, + created_at, updated_at, deleted_at, + meta, external_entity_type, required, regex, + tenant_code, organization_code +) VALUES +(5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(10, 'professional_role', 'Professional Role', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'), + +(11, 'professional_subroles', 'Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', + now(), now(), NULL, + '{"service":"entity-management-service","endPoint":"v1/entities/find"}', + true, false, NULL, 'default', 'default_code'); + +-- ---------------- SEQUENCE FIX ---------------- +SELECT setval('users_id_seq', (SELECT MAX(id) FROM public.users)); +SELECT setval('entity_types_id_seq', (SELECT MAX(id) FROM public.entity_types)); + +COMMIT; diff --git a/documentation/3.4.0/native/envs/non-citus/notification_env b/documentation/3.4.0/native/envs/non-citus/notification_env new file mode 100644 index 00000000..419184a2 --- /dev/null +++ b/documentation/3.4.0/native/envs/non-citus/notification_env @@ -0,0 +1,14 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/notification/ +APPLICATION_ENV=development +APPLICATION_PORT=3002 +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/notification +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +INTERNAL_ACCESS_TOKEN=internal_access_token +KAFKA_GROUP_ID=notification +KAFKA_HOST=kafka:9092 +KAFKA_TOPIC=develop.notifications +SENDGRID_API_KEY=SG.asd9f87a9s8d7f. +SENDGRID_FROM_MAIL=no-reply@some.org \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/non-citus/user_env b/documentation/3.4.0/native/envs/non-citus/user_env new file mode 100644 index 00000000..e9bc7827 --- /dev/null +++ b/documentation/3.4.0/native/envs/non-citus/user_env @@ -0,0 +1,74 @@ +ACCESS_TOKEN_EXPIRY=30m +ACCESS_TOKEN_SECRET=hsghasghjab1273JHajnbabsjdj1273981273jhajksdh8y3123yhjkah812398yhjqwe7617237yuhdhhdqwu271 +ADMIN_INVITEE_UPLOAD_EMAIL_TEMPLATE_CODE=test +ADMIN_SECRET_CODE=a98sd76fasdfasd +API_DOC_URL=/user/api-doc +APPLICATION_ENV=development +APPLICATION_HOST=localhost +APPLICATION_PORT=3001 +APP_NAME=ELEVATE-Project +AZURE_ACCOUNT_KEY=asd897gfa09sd87f09as8d +AZURE_ACCOUNT_NAME=mentoring +AWS_ACCESS_KEY_ID=adsfg98a7sdfg +AWS_BUCKET_ENDPOINT=s3.ap-south-1.amazonaws.com +AWS_BUCKET_REGION=ap-south-1 +AWS_SECRET_ACCESS_KEY=asd9786fg9a8sd/asdfg9a8sd7fg +CAPTCHA_ENABLE=false +CHANGE_PASSWORD_TEMPLATE_CODE=change_password +CLEAR_INTERNAL_CACHE=userinternal +DEFAULT_ORGANISATION_CODE=default_code +DEFAULT_ORG_ID=1 +DEFAULT_ROLE=mentee +DEFAULT_QUEUE=test +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/users +DISABLE_LOG=false +EMAIL_ID_ENCRYPTION_ALGORITHM=aes-256-cbc +EMAIL_ID_ENCRYPTION_IV=c9c7bd480494409071847264652f5c95 +EMAIL_ID_ENCRYPTION_KEY=eef7e009626c18724be86afa41a2620e0718561a508c61f92d7ee0377177ef7b +ENABLE_EMAIL_OTP_VERIFICATION=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +EVENT_ENABLE_ORG_EVENTS=true +EVENT_ORG_LISTENER_URLS=http://localhost:3567/mentoring/v1/organization/eventListener +GCP_PATH=gcp.json +GCP_PROJECT_ID=sl-dev-project +INTERNAL_ACCESS_TOKEN=internal_access_token +INTERNAL_CACHE_EXP_TIME=86400 +INVITEE_EMAIL_TEMPLATE_CODE=test +IV=09sdf8g098sdf/Q== +KAFKA_GROUP_ID=projects +KAFKA_TOPIC= +KAFKA_URL=localhost:9092 +KEY=fasd98fg9a8sydg98a7usd89fg +MENTEE_INVITATION_EMAIL_TEMPLATE_CODE=test +MENTOR_INVITATION_EMAIL_TEMPLATE_CODE=test +MENTOR_REQUEST_ACCEPTED_EMAIL_TEMPLATE_CODE=mentor_request_accepted +MENTOR_REQUEST_REJECTED_EMAIL_TEMPLATE_CODE=mentor_request_rejected +MENTORING_SERVICE_URL=http://mentoring:3000 +NOTIFICATION_KAFKA_TOPIC=develop.notifications +ORG_ADMIN_INVITATION_EMAIL_TEMPLATE_CODE=invite_org_admin +OTP_EMAIL_TEMPLATE_CODE=emailotp +OTP_EXP_TIME=86400 +PORTAL_URL=https://mentored.some.org/auth/login +RECAPTCHA_SECRET_KEY=temporary_recaptcha_secret_key +REFRESH_TOKEN_EXPIRY=7 +REFRESH_TOKEN_SECRET=as9d87fa9s87df98as7d9f87a9sd87f98as7dg987asf +REFRESH_VIEW_INTERVAL=540000 +REDIS_HOST=http://localhost:6379 +REGISTRATION_EMAIL_TEMPLATE_CODE=registration +REGISTRATION_OTP_EMAIL_TEMPLATE_CODE=registrationotp +SAMPLE_CSV_FILE_PATH=sample/bulk_user_creation.csv +SCHEDULER_SERVICE_BASE_URL= /scheduler/ +SCHEDULER_SERVICE_ERROR_REPORTING_EMAIL_ID=rakesh.k@some.com +SCHEDULER_SERVICE_HOST=http://localhost:4000 +SCHEDULER_SERVICE_URL=http://localhost:4000/jobs/scheduleJob +ALLOWED_HOST=http://localhost:8100 +CLOUD_STORAGE=GCP +CLOUD_STORAGE_ACCOUNTNAME=sl-mentoring-dev-storage@sl-dev-project.iam.gserviceaccount.com +CLOUD_STORAGE_BUCKETNAME=mentoring-dev-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +CLOUD_STORAGE_PROJECT=sl-dev-project +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_SECRET=qwrthgafyadady +APPLICATION_BASE_URL='/user' +PUBLIC_ASSET_BUCKETNAME=check \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/project-with-survey/entity_management_env b/documentation/3.4.0/native/envs/project-with-survey/entity_management_env new file mode 100644 index 00000000..f6c12cfd --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/entity_management_env @@ -0,0 +1,22 @@ +APPLICATION_PORT = 5001 +APPLICATION_ENV ="development" +APPLICATION_BASE_URL='/entity-management/' +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +MONGODB_URL=mongodb://localhost:27017/elevate-entity +AUTH_METHOD = native +USER_SERVICE_URL = http://localhost:3569 +USER_SERVICE_BASE_URL=/user +KAFKA_HEALTH_CHECK_TOPIC=test +SERVICE_NAME = elevate-entity-service +API_DOC_URL="http://localhost:5001/entity-management/api-doc" +APPLICATION_HOST=localhost +IS_AUTH_TOKEN_BEARER="false" +ADMIN_ACCESS_TOKEN=rwwee3$123 +ADMIN_TOKEN_HEADER_NAME="admin-auth-token" +INTERFACE_SERVICE_URL=http://localhost:3569 +KAFKA_HEALTH_CHECK_TOPIC = entity-health-check-topic-check +KAFKA_URL = localhost:9092 +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_GROUP_ID = entity +HEALTH_CHECK_DEBUG_MODE = true \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/project-with-survey/interface_env b/documentation/3.4.0/native/envs/project-with-survey/interface_env new file mode 100644 index 00000000..4eee9dd5 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/interface_env @@ -0,0 +1,24 @@ +API_DOC_URL=/interface/api-doc +APPLICATION_ENV=development +APPLICATION_PORT=3569 +ELEVATE_NOTIFICATION_KAFKA_BROKERS=localhost:9092 +ELEVATE_NOTIFICATION_KAFKA_GROUP_ID=dev.mentoring +ELEVATE_NOTIFICATION_KAFKA_TOPIC=dev.notification +ENTITY_SERVICE_BASE_URL=http://localhost:5001 +INSTALLED_PACKAGES=elevate-mentoring elevate-survey-observation@1.0.1 elevate-self-creation-portal +NOTIFICATION_SERVICE_BASE_URL=http://localhost:7201 +PROJECT_SERVICE_BASE_URL=http://localhost:6000 +RATE_LIMITER_ENABLED=true +RATE_LIMITER_GENERAL_LIMIT=500 +RATE_LIMITER_NUMBER_OF_PROXIES=3 +RATE_LIMITER_PUBLIC_LOW_LIMIT=5 +REQUIRED_BASE_PACKAGES=elevate-mentoring elevate-project elevate-survey-observation self-creation-portal +REQUIRED_PACKAGES=elevate-mentoring@1.2.90 elevate-survey-observation@1.0.22 elevate-project@1.1.53 shiksha-notification@1.1.3 elevate-self-creation-portal@1.0.70 +ROUTE_CONFIG_JSON_URLS_PATHS=https://raw.githubusercontent.com/ELEVATE-Project/utils/refs/heads/master/interface-routes/elevate-routes.json +SAAS_NOTIFICATION_BASE_URL=interface/v1/notification/send-raw +SAAS_NOTIFICATION_SEND_EMAIL_ROUTE=interface/v1/notification/send-raw +SAMIKSHA_SERVICE_BASE_URL=http://localhost:4301 +SCHEDULER_SERVICE_BASE_URL=http://localhost:7401 +SUPPORTED_HTTP_TYPES=GET POST PUT PATCH DELETE +SURVEY_SERVICE_BASE_URL=http://localhost:4301 +USER_SERVICE_BASE_URL=http://localhost:3001 \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/project-with-survey/notification_env b/documentation/3.4.0/native/envs/project-with-survey/notification_env new file mode 100644 index 00000000..18cf3570 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/notification_env @@ -0,0 +1,17 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/notification/ +APPLICATION_ENV=development +APPLICATION_PORT=3002 +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/notification +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +KAFKA_GROUP_ID=notification +KAFKA_HOST=localhost:9092 +KAFKA_TOPIC=develop.notifications +SENDGRID_API_KEY=SG.asd9f87a9s8d7f. +SENDGRID_FROM_MAIL=no-reply@some.org +ZEST_ENV=ZEST_ENV +EMAIL_SERVICE=email +FROM_EMAIL=email diff --git a/documentation/3.4.0/native/envs/project-with-survey/project_env b/documentation/3.4.0/native/envs/project-with-survey/project_env new file mode 100644 index 00000000..7af79774 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/project_env @@ -0,0 +1,49 @@ +APPLICATION_PORT = 6000 +APPLICATION_ENV = development +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +MONGODB_URL = mongodb://localhost:27017/elevate-project +KEYCLOAK_PUBLIC_KEY_PATH = keycloak-public-keys +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_URL=localhost:9092 +KAFKA_GROUP_ID = projects +KAFKA_HEALTH_CHECK_TOPIC = project-health-check-topic-check +PROJECT_SUBMISSION_TOPIC=sl-improvement-project-submission-dev +SUBMISSION_TOPIC = Projectsubmissions +PROJECT_CERTIFICATE_TOPIC = generateProjectCertificate +ELEVATE_PROJECT_SERVICE_URL= 'http://localhost:6000' +SERVICE_NAME = project +USER_DELETE_TOPIC = deleteuser +TELEMETRY_TOPIC=telemetry.raw +ID = projectservice +TELEMETRY_ON_OFF=ON +USER_DELETE_ON_OFF=OFF +CLOUD_STORAGE=ON +TIMEZONE_DIFFRENECE_BETWEEN_LOCAL_TIME_AND_UTC = +05:30 +VALIDATE_ENTITIES = ON +APP_PORTAL_BASE_URL = "http://localhost:7007" +NO_OF_MINUTES = 30 +NO_OF_EXPIRY_TIME = 60 +DEFAULT_ORGANISATION_CODE = default_code +GOTENBERG_URL=http://localhost:3000 +API_DOC_URL="http://http://localhost:3569/project/api-doc" +INTERFACE_SERVICE_URL=http://localhost:3569 +USER_SERVICE_BASE_URL = "/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL = "/entity-management" +SURVEY_SERVICE_URL = http://localhost:4301/survey +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_ACCOUNTNAME=CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n" +CLOUD_STORAGE_PROJECT =sl-dev-project +CLOUD_STORAGE_BUCKETNAME=mentoring-dev-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +ADMIN_ACCESS_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_AUTH_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_TOKEN_HEADER_NAME = 'admin-auth-token' +IS_AUTH_TOKEN_BEARER = false +AUTH_METHOD = native +REDIS_HOST=redis://127.0.0.1:6379 +USER_SERVICE_URL = http://localhost:3569 +RESOURCE_DELETION_TOPIC=RESOURCE_DELETION_TOPIC +PROGRAM_USER_MAPPING_TOPIC=local.program +SESSION_VERIFICATION_METHOD=user_service_authenticated \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/project-with-survey/samiksha_env b/documentation/3.4.0/native/envs/project-with-survey/samiksha_env new file mode 100644 index 00000000..865372f2 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/samiksha_env @@ -0,0 +1,66 @@ +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +ADMIN_ACCESS_TOKEN=CN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_AUTH_TOKEN=CN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_TOKEN_HEADER_NAME=admin-auth-token +API_DOC_URL=/survey/api-doc +APPLICATION_BASE_URL=/survey/ +APP_PORTAL_BASE_URL=http://localhost:7007 +APP_PORTAL_DIRECTORY=/observations/ +AUTH_CONFIG_FILE_PATH=config.json +AUTH_METHOD=native +CLOUD_STORAGE=GCP +CLOUD_STORAGE_ACCOUNTNAME=CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_BUCKETNAME=mentoring-dev-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +CLOUD_STORAGE_PROJECT=sl-dev-project +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_SECRET=----BEGIN PRIVATE KEY----- +COMPLETED_OBSERVATION_SUBMISSION_TOPIC=elevate_observations_dev +COMPLETED_SUBMISSION_TOPIC=elevate_submissions_dev +COMPLETED_SURVEY_SUBMISSION_TOPIC=elevate_surveys_raw_dev +CSV_REPORTS_PATH=reports +DB=elevate-samiksha +DEFAULT_ORGANISATION_CODE=default_code +ELEVATE_SURVEY_SERVICE_URL=http://localhost:7007 +ENTITY_BASE_URL=http://localhost:3569 +ENTITY_MANAGEMENT_SERVICE_URL=http://localhost:3569/entity-management +GOTENBERG_URL=http://localhost:3000 +HOST=localhost +IMPROVEMENT_PROJECT_BASE_URL=http://localhost:3569 +IMPROVEMENT_PROJECT_SUBMISSION_TOPIC=elevate_project_task_submissions_dev +INCOMPLETE_OBSERVATION_SUBMISSION_TOPIC=elevate_observations_dev +INCOMPLETE_SUBMISSION_TOPIC=elevate_submissions_dev +INCOMPLETE_SURVEY_SUBMISSION_TOPIC=elevate_surveys_raw_dev +INTERFACE_SERVICE_URL=http://localhost:3569 +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +IS_AUTH_TOKEN_BEARER=false +Instance=ELEVATE +KAFKA_COMMUNICATIONS_ON_OFF=ON +KAFKA_GROUP_ID=dev.survey +KAFKA_HEALTH_CHECK_TOPIC=survey-health-check-topic-check +KAFKA_URL=localhost:9092 +LOG=debug +MOBILE_APPLICATION_APP_TYPE=assessment +MONGODB_URL=mongodb://localhost:27017 +NODE_ENV=development +NOTIFICATIONS_TOPIC=elevate_notifications_dev +ORG_UPDATES_TOPIC=dev.organizationEvent +PORT=4301 +PROGRAM_USER_MAPPING_TOPIC=dev.program +PROJECT_SERVICE_NAME=/project +PUBLIC_FOLDER_PATH=public +REQUEST_TIMEOUT_FOR_REPORTS=600000 +SERVICE_NAME=survey +SERVICE_NAME_HEALTH_CHECK=SamikshaService +SUBMISSION_RATING_QUEUE_TOPIC=elevate_submissions_rating_dev +SUBMISSION_UPDATE_KAFKA_PUSH_ON_OFF=ON +TIMEZONE_DIFFRENECE_BETWEEN_LOCAL_TIME_AND_UTC=+05:30 +TOP_LEVEL_ENTITY_TYPE=state +USER_ACCOUNT_EVENT_TOPIC=dev.userCreate +USER_COURSES_SUBMISSION_TOPIC=elevate_user_courses_dev +USER_COURSES_TOPIC=elevate_user_courses_raw +USER_DELETE_ON_OFF=ON +USER_DELETE_TOPIC=dev.userCreate +USER_SERVICE_URL=http://localhost:3569/user +VALIDATE_ENTITIES=ON +VALIDATE_ROLE=ON diff --git a/documentation/3.4.0/native/envs/project-with-survey/scheduler_env b/documentation/3.4.0/native/envs/project-with-survey/scheduler_env new file mode 100644 index 00000000..fa7dbfa1 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/scheduler_env @@ -0,0 +1,13 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/scheduler/ +APPLICATION_ENV=development +APPLICATION_PORT=4000 +DEFAULT_QUEUE=email +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +KAFKA_URL=localhost:9092 +NOTIFICATION_KAFKA_TOPIC=develop.notifications +REDIS_HOST=localhost +REDIS_PORT=6379 +MONGODB_URL="mongodb://localhost:27017/tl-cron-rest" diff --git a/documentation/3.4.0/native/envs/project-with-survey/user_env b/documentation/3.4.0/native/envs/project-with-survey/user_env new file mode 100644 index 00000000..a10d1f23 --- /dev/null +++ b/documentation/3.4.0/native/envs/project-with-survey/user_env @@ -0,0 +1,82 @@ +ACCESS_TOKEN_EXPIRY='30m' +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +API_DOC_URL=/user/api-doc +APP_NAME=MentorED +APPLICATION_ENV=development +APPLICATION_PORT=3001 +CLOUD_STORAGE_PROVIDER = aws +CLOUD_STORAGE_BUCKETNAME =mentoring-prod-storage-private +CLOUD_STORAGE_SECRET= CLOUD_STORAGE_SECRET +CLOUD_STORAGE_REGION =ap-south-1 +CLOUD_ENDPOINT =CLOUD_ENDPOINT +CLOUD_STORAGE_ACCOUNTNAME =CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_BUCKET_TYPE = private +PUBLIC_ASSET_BUCKETNAME=mentoring-prod-storage-private +AZURE_ACCOUNT_KEY='AZURE_ACCOUNT_KEY' +AZURE_ACCOUNT_NAME=elevatementoringaccount +CLEAR_INTERNAL_CACHE=userinternal +CLOUD_STORAGE=GCP +DEFAULT_AZURE_CONTAINER_NAME=mentoring-azure-private +DEFAULT_GCP_BUCKET_NAME=DEFAULT_GCP_BUCKET_NAME +ENABLE_EMAIL_OTP_VERIFICATION=false +ENABLE_LOG=true +GCP_PATH=gcp.json +GCP_PROJECT_ID=sl-project +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +INTERNAL_CACHE_EXP_TIME=86400 +IV=LHYOA5YnTonqcgrm15k3/Q== +KAFKA_GROUP_ID=mentoring +KAFKA_TOPIC= +KAFKA_URL= localhost:9092 +KEY=E/m3RD/aM3Ed3lLfYVcKizakG9R+bFybAPZSLjIP2hY= +MENTOR_SECRET_CODE=4567 +MONGODB_URL=mongodb://localhost:27017/elevate-users +NOTIFICATION_KAFKA_TOPIC=notifications +OTP_EMAIL_TEMPLATE_CODE=emailotp +OTP_EXP_TIME=86400 +RATING_KAFKA_TOPIC=mentor_rating +REDIS_HOST=redis://localhost:6379 +REFRESH_TOKEN_EXPIRY=183 +REFRESH_TOKEN_SECRET=371hkjkjady2y3ihdkajshdkiq23iuekw71yekhaskdvkvegavy23t78veqwexqvxveit6ttxyeeytt62tx236vv +REGISTRATION_EMAIL_TEMPLATE_CODE=registration +REGISTRATION_OTP_EMAIL_TEMPLATE_CODE=registrationotp +SALT_ROUNDS=10 +MENTORING_SERVICE_URL='localhost' +DEFAULT_OCI_BUCKET_NAME=mentoring-oci-private +OCI_ACCESS_KEY_ID= 81a4c2553026982360af6b24497c489b0fea9436 +OCI_BUCKET_ENDPOINT=https://axgqmpkrpmt5.compat.objectstorage.ap-hyderabad-1.oraclecloud.com +OCI_BUCKET_REGION= ap-hyderabad-1 +OCI_SECRET_ACCESS_KEY='+U4O+CjiC6M/mOcGjYh7K/9XjfSdJ79OoLuQrABPOJ8=' +ERROR_LOG_LEVEL= silly +DISABLE_LOG= false +DEFAULT_ORGANISATION_CODE=default_code +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/users +ADMIN_SECRET_CODE=W5bF7gesuS0xsNWmpsKy +INVITEE_EMAIL_TEMPLATE_CODE="emailcode" +ADMIN_INVITEE_UPLOAD_EMAIL_TEMPLATE_CODE="coeadmin" +DEFAULT_QUEUE="defaultque" +MENTOR_INVITATION_EMAIL_TEMPLATE_CODE="mentorinvitationTemplateCode" +MENTEE_INVITATION_EMAIL_TEMPLATE_CODE="mentee invitationTemplateCode" +DEFAULT_ROLE="mentee" +SAMPLE_CSV_FILE_PATH="sample path" +ORG_ADMIN_INVITATION_EMAIL_TEMPLATE_CODE = "all" +DEFAULT_ORG_ID = 1 +IS_AUTH_TOKEN_BEARER=false +PORTAL_URL = "portaladdress" +SCHEDULER_SERVICE_HOST = "host" +SCHEDULER_SERVICE_BASE_URL = "/scheduler/" +REFRESH_VIEW_INTERVAL = 100000 +EMAIL_ID_ENCRYPTION_IV = 'a390328e496f025249a88384f318a536' +EMAIL_ID_ENCRYPTION_KEY = '9bbf4698e081176b4e38c3f04f9c0cff6ae80b1960e5ac868cc234ac8537aa66' +EMAIL_ID_ENCRYPTION_ALGORITHM = 'aes-256-cbc' +GENERIC_INVITATION_EMAIL_TEMPLATE_CODE = 'check_code' +EVENT_ORG_LISTENER_URLS = "sample url" +EVENT_ENABLE_ORG_EVENTS = false +DOWNLOAD_URL_EXPIRATION_DURATION = 300 +APPLICATION_HOST= "localhost" +CHANGE_PASSWORD_TEMPLATE_CODE = "change_password" +CAPTCHA_ENABLE = false +RECAPTCHA_SECRET_KEY= "6LfWEKYpAAAAAJS0eukS2Su_5vwlXRs5vPbC34W0" +ALLOWED_IDLE_TIME=1200000 +APPLICATION_BASE_URL="/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL="http://localhost:3569/entity-management/" \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/stand-alone/entity_management_env b/documentation/3.4.0/native/envs/stand-alone/entity_management_env new file mode 100644 index 00000000..25f67bef --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/entity_management_env @@ -0,0 +1,22 @@ +APPLICATION_PORT = 5001 +APPLICATION_ENV ="development" +APPLICATION_BASE_URL='/entity-management/' +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +MONGODB_URL=mongodb://localhost:27017/elevate-entity +AUTH_METHOD = native +USER_SERVICE_URL = http://localhost:3569 +USER_SERVICE_BASE_URL=/user +KAFKA_HEALTH_CHECK_TOPIC=test +SERVICE_NAME = elevate-entity-service +API_DOC_URL="http://localhost:3569/entity-management/api-doc" +APPLICATION_HOST=localhost +IS_AUTH_TOKEN_BEARER="false" +ADMIN_ACCESS_TOKEN=rwwee3$123 +ADMIN_TOKEN_HEADER_NAME="admin-auth-token" +INTERFACE_SERVICE_URL=http://localhost:3569 +KAFKA_HEALTH_CHECK_TOPIC = entity-health-check-topic-check +KAFKA_URL = kafka:9092 +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_GROUP_ID = entity +HEALTH_CHECK_DEBUG_MODE = true \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/stand-alone/interface_env b/documentation/3.4.0/native/envs/stand-alone/interface_env new file mode 100644 index 00000000..8a78566e --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/interface_env @@ -0,0 +1,24 @@ +API_DOC_URL=/interface/api-doc +APPLICATION_ENV=development +APPLICATION_PORT=3569 +ELEVATE_NOTIFICATION_KAFKA_BROKERS=localhost:9092 +ELEVATE_NOTIFICATION_KAFKA_GROUP_ID=dev.mentoring +ELEVATE_NOTIFICATION_KAFKA_TOPIC=dev.notification +ENTITY_SERVICE_BASE_URL=http://localhost:5001 +INSTALLED_PACKAGES=elevate-mentoring elevate-survey-observation@1.0.1 elevate-self-creation-portal +NOTIFICATION_SERVICE_BASE_URL=http://localhost:7201 +PROJECT_SERVICE_BASE_URL=http://localhost:6000 +RATE_LIMITER_ENABLED=true +RATE_LIMITER_GENERAL_LIMIT=500 +RATE_LIMITER_NUMBER_OF_PROXIES=3 +RATE_LIMITER_PUBLIC_LOW_LIMIT=5 +REQUIRED_BASE_PACKAGES=elevate-mentoring elevate-project elevate-survey-observation self-creation-portal +REQUIRED_PACKAGES=elevate-mentoring@1.2.90 elevate-survey-observation@1.0.22 elevate-project@1.1.53 shiksha-notification@1.1.3 elevate-self-creation-portal@1.0.70 +ROUTE_CONFIG_JSON_URLS_PATHS=https://raw.githubusercontent.com/ELEVATE-Project/utils/refs/heads/master/interface-routes/elevate-routes.json +SAAS_NOTIFICATION_BASE_URL=interface/v1/notification/send-raw +SAAS_NOTIFICATION_SEND_EMAIL_ROUTE=interface/v1/notification/send-raw +SAMIKSHA_SERVICE_BASE_URL=http://localhost:5007 +SCHEDULER_SERVICE_BASE_URL=http://localhost:7401 +SUPPORTED_HTTP_TYPES=GET POST PUT PATCH DELETE +SURVEY_SERVICE_BASE_URL=http://localhost:5007 +USER_SERVICE_BASE_URL=http://localhost:3001 \ No newline at end of file diff --git a/documentation/3.4.0/native/envs/stand-alone/notification_env b/documentation/3.4.0/native/envs/stand-alone/notification_env new file mode 100644 index 00000000..18cf3570 --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/notification_env @@ -0,0 +1,17 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/notification/ +APPLICATION_ENV=development +APPLICATION_PORT=3002 +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/notification +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +KAFKA_GROUP_ID=notification +KAFKA_HOST=localhost:9092 +KAFKA_TOPIC=develop.notifications +SENDGRID_API_KEY=SG.asd9f87a9s8d7f. +SENDGRID_FROM_MAIL=no-reply@some.org +ZEST_ENV=ZEST_ENV +EMAIL_SERVICE=email +FROM_EMAIL=email diff --git a/documentation/3.4.0/native/envs/stand-alone/project_env b/documentation/3.4.0/native/envs/stand-alone/project_env new file mode 100644 index 00000000..775e3d2f --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/project_env @@ -0,0 +1,51 @@ +APPLICATION_PORT = 6000 +APPLICATION_ENV = development +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +INTERNAL_ACCESS_TOKEN =xahusub12yexlashsbxAXADHBlaj +MONGODB_URL = mongodb://localhost:27017/elevate-project +KEYCLOAK_PUBLIC_KEY_PATH = keycloak-public-keys +KAFKA_COMMUNICATIONS_ON_OFF = ON +KAFKA_URL=localhost:9092 +KAFKA_GROUP_ID = projects +KAFKA_HEALTH_CHECK_TOPIC = project-health-check-topic-check +PROJECT_SUBMISSION_TOPIC=sl-improvement-project-submission-dev +SUBMISSION_TOPIC = Projectsubmissions +PROJECT_CERTIFICATE_TOPIC = generateProjectCertificate +ELEVATE_PROJECT_SERVICE_URL= 'http://localhost:6000' +SERVICE_NAME = project +USER_DELETE_TOPIC = deleteuser +TELEMETRY_TOPIC=telemetry.raw +ID = projectservice +TELEMETRY_ON_OFF=ON +USER_DELETE_ON_OFF=OFF +CLOUD_STORAGE=ON +TIMEZONE_DIFFRENECE_BETWEEN_LOCAL_TIME_AND_UTC = +05:30 +VALIDATE_ENTITIES = ON +APP_PORTAL_BASE_URL = "http://localhost:7007" +NO_OF_MINUTES = 30 +NO_OF_EXPIRY_TIME = 60 +DEFAULT_ORGANISATION_CODE = default_code +GOTENBERG_URL=http://localhost:3000 +API_DOC_URL="http://http://localhost:3569/project/api-doc" +INTERFACE_SERVICE_URL=http://localhost:3569 +USER_SERVICE_BASE_URL = "/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL = "/entity-management" +SURVEY_SERVICE_URL = http://localhost:4301/survey +CLOUD_STORAGE_PROVIDER=gcloud +CLOUD_STORAGE_ACCOUNTNAME=CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n" +CLOUD_STORAGE_PROJECT =sl-dev-project +CLOUD_STORAGE_BUCKETNAME=mentoring-dev-storage-private +CLOUD_STORAGE_BUCKET_TYPE=private +ADMIN_ACCESS_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_AUTH_TOKEN = N0DM5NAwwCN5KNXKJwlwu6c0nQQt6Rcl +ADMIN_TOKEN_HEADER_NAME = 'admin-auth-token' +IS_AUTH_TOKEN_BEARER = false +AUTH_METHOD = native +REDIS_HOST=redis://127.0.0.1:6379 +USER_SERVICE_URL = http://localhost:3569 +RESOURCE_DELETION_TOPIC=RESOURCE_DELETION_TOPIC +PROGRAM_USER_MAPPING_TOPIC=local.program +SESSION_VERIFICATION_METHOD=user_service_authenticated + + diff --git a/documentation/3.4.0/native/envs/stand-alone/scheduler_env b/documentation/3.4.0/native/envs/stand-alone/scheduler_env new file mode 100644 index 00000000..fa7dbfa1 --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/scheduler_env @@ -0,0 +1,13 @@ +API_DOC_URL=/api-doc +APPLICATION_BASE_URL=/scheduler/ +APPLICATION_ENV=development +APPLICATION_PORT=4000 +DEFAULT_QUEUE=email +DISABLE_LOG=false +ENABLE_LOG=true +ERROR_LOG_LEVEL=silly +KAFKA_URL=localhost:9092 +NOTIFICATION_KAFKA_TOPIC=develop.notifications +REDIS_HOST=localhost +REDIS_PORT=6379 +MONGODB_URL="mongodb://localhost:27017/tl-cron-rest" diff --git a/documentation/3.4.0/native/envs/stand-alone/user_env b/documentation/3.4.0/native/envs/stand-alone/user_env new file mode 100644 index 00000000..193d7859 --- /dev/null +++ b/documentation/3.4.0/native/envs/stand-alone/user_env @@ -0,0 +1,82 @@ +ACCESS_TOKEN_EXPIRY='30m' +ACCESS_TOKEN_SECRET=bsj82AHBxahusub12yexlashsbxAXADHBlaj +API_DOC_URL=/user/api-doc +APP_NAME=MentorED +APPLICATION_ENV=development +APPLICATION_PORT=3001 +CLOUD_STORAGE_PROVIDER = aws +CLOUD_STORAGE_BUCKETNAME =mentoring-prod-storage-private +CLOUD_STORAGE_SECRET= CLOUD_STORAGE_SECRET +CLOUD_STORAGE_REGION =ap-south-1 +CLOUD_ENDPOINT =CLOUD_ENDPOINT +CLOUD_STORAGE_ACCOUNTNAME =CLOUD_STORAGE_ACCOUNTNAME +CLOUD_STORAGE_BUCKET_TYPE = private +PUBLIC_ASSET_BUCKETNAME=mentoring-prod-storage-private +AZURE_ACCOUNT_KEY='AZURE_ACCOUNT_KEY' +AZURE_ACCOUNT_NAME=elevatementoringaccount +CLEAR_INTERNAL_CACHE=userinternal +CLOUD_STORAGE=GCP +DEFAULT_AZURE_CONTAINER_NAME=mentoring-azure-private +DEFAULT_GCP_BUCKET_NAME=DEFAULT_GCP_BUCKET_NAME +ENABLE_EMAIL_OTP_VERIFICATION=false +ENABLE_LOG=true +GCP_PATH=gcp.json +GCP_PROJECT_ID=sl-project +INTERNAL_ACCESS_TOKEN=xahusub12yexlashsbxAXADHBlaj +INTERNAL_CACHE_EXP_TIME=86400 +IV=LHYOA5YnTonqcgrm15k3/Q== +KAFKA_GROUP_ID=mentoring +KAFKA_TOPIC= +KAFKA_URL= localhost:9092 +KEY=E/m3RD/aM3Ed3lLfYVcKizakG9R+bFybAPZSLjIP2hY= +MENTOR_SECRET_CODE=4567 +MONGODB_URL=mongodb://localhost:27017/elevate-users +NOTIFICATION_KAFKA_TOPIC=notifications +OTP_EMAIL_TEMPLATE_CODE=emailotp +OTP_EXP_TIME=86400 +RATING_KAFKA_TOPIC=mentor_rating +REDIS_HOST=redis://localhost:6379 +REFRESH_TOKEN_EXPIRY=183 +REFRESH_TOKEN_SECRET=371hkjkjady2y3ihdkajshdkiq23iuekw71yekhaskdvkvegavy23t78veqwexqvxveit6ttxyeeytt62tx236vv +REGISTRATION_EMAIL_TEMPLATE_CODE=registration +REGISTRATION_OTP_EMAIL_TEMPLATE_CODE=registrationotp +SALT_ROUNDS=10 +MENTORING_SERVICE_URL='localhost' +DEFAULT_OCI_BUCKET_NAME=mentoring-oci-private +OCI_ACCESS_KEY_ID= 81a4c2553026982360af6b24497c489b0fea9436 +OCI_BUCKET_ENDPOINT=https://axgqmpkrpmt5.compat.objectstorage.ap-hyderabad-1.oraclecloud.com +OCI_BUCKET_REGION= ap-hyderabad-1 +OCI_SECRET_ACCESS_KEY='+U4O+CjiC6M/mOcGjYh7K/9XjfSdJ79OoLuQrABPOJ8=' +ERROR_LOG_LEVEL= silly +DISABLE_LOG= false +DEFAULT_ORGANISATION_CODE=default_code +DEV_DATABASE_URL=postgres://postgres:postgres@localhost:5432/users +ADMIN_SECRET_CODE=W5bF7gesuS0xsNWmpsKy +INVITEE_EMAIL_TEMPLATE_CODE="emailcode" +ADMIN_INVITEE_UPLOAD_EMAIL_TEMPLATE_CODE="coeadmin" +DEFAULT_QUEUE="defaultque" +MENTOR_INVITATION_EMAIL_TEMPLATE_CODE="mentorinvitationTemplateCode" +MENTEE_INVITATION_EMAIL_TEMPLATE_CODE="mentee invitationTemplateCode" +DEFAULT_ROLE="mentee" +SAMPLE_CSV_FILE_PATH="sample path" +ORG_ADMIN_INVITATION_EMAIL_TEMPLATE_CODE = "code5" +DEFAULT_ORG_ID = 1 +IS_AUTH_TOKEN_BEARER=false +PORTAL_URL = "portaladdress" +SCHEDULER_SERVICE_HOST = "host" +SCHEDULER_SERVICE_BASE_URL = "/scheduler/" +REFRESH_VIEW_INTERVAL = 100000 +EMAIL_ID_ENCRYPTION_IV = 'a390328e496f025249a88384f318a536' +EMAIL_ID_ENCRYPTION_KEY = '9bbf4698e081176b4e38c3f04f9c0cff6ae80b1960e5ac868cc234ac8537aa66' +EMAIL_ID_ENCRYPTION_ALGORITHM = 'aes-256-cbc' +GENERIC_INVITATION_EMAIL_TEMPLATE_CODE = 'check_code' +EVENT_ORG_LISTENER_URLS = "sample url" +EVENT_ENABLE_ORG_EVENTS = false +DOWNLOAD_URL_EXPIRATION_DURATION = 300 +APPLICATION_HOST= "localhost" +CHANGE_PASSWORD_TEMPLATE_CODE = "change_password" +CAPTCHA_ENABLE = false +RECAPTCHA_SECRET_KEY= "6LfWEKYpAAAAAJS0eukS2Su_5vwlXRs5vPbC34W0" +ALLOWED_IDLE_TIME=1200000 +APPLICATION_BASE_URL="/user" +ENTITY_MANAGEMENT_SERVICE_BASE_URL="http://localhost:3569/entity-management/" \ No newline at end of file diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/check-dependencies.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/check-dependencies.sh new file mode 100644 index 00000000..98ff5e8b --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/check-dependencies.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +# Define ANSI color codes for output formatting +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Function to check Node.js installation +check_nodejs() { + if command -v node > /dev/null 2>&1; then + echo -e "${GREEN}Node.js is installed. Version: $(node --version)${NC}" + else + echo -e "${RED}Node.js is not installed.${NC}" + fi +} + +# Function to check Apache Kafka and Zookeeper installation +check_kafka() { + if [ -d "/opt/kafka" ]; then + echo -e "${GREEN}Kafka directory exists.${NC}" + else + echo -e "${RED}Kafka directory does not exist.${NC}" + fi + + if systemctl is-active --quiet zookeeper; then + echo -e "${GREEN}Zookeeper service is running.${NC}" + else + echo -e "${RED}Zookeeper service is not running.${NC}" + fi + + if systemctl is-active --quiet kafka; then + echo -e "${GREEN}Kafka service is running.${NC}" + else + echo -e "${RED}Kafka service is not running.${NC}" + fi +} + +# Function to check Redis installation and service status +check_redis() { + if command -v redis-server > /dev/null 2>&1; then + echo -e "${GREEN}Redis server is installed. Version: $(redis-server --version)${NC}" + else + echo -e "${RED}Redis server is not installed.${NC}" + return + fi + + if systemctl status redis-server.service &> /dev/null; then + echo -e "${GREEN}Redis service is running.${NC}" + else + echo -e "${RED}Redis service is not running or inactive.${NC}" + fi +} + +# Function to check Citus installation +check_citus() { + if sudo su - postgres -c "psql -p 9700 -c 'SELECT citus_version();'" &> /dev/null; then + echo -e "${GREEN}Citus is running on port 9700.${NC}" + else + echo -e "${RED}Citus is not running or not installed.${NC}" + fi +} + +# Function to check PM2 installation +check_pm2() { + if command -v pm2 > /dev/null 2>&1; then + echo -e "${GREEN}PM2 is installed. Version: $(pm2 -v)${NC}" + else + echo -e "${RED}PM2 is not installed.${NC}" + fi +} + +# Function to check PostgreSQL installation and service +check_postgres() { + if command -v psql > /dev/null 2>&1; then + echo -e "${GREEN}PostgreSQL is installed. Version: $(psql --version)${NC}" + else + echo -e "${RED}PostgreSQL is not installed.${NC}" + fi + + if systemctl is-active --quiet postgresql; then + echo -e "${GREEN}PostgreSQL service is running.${NC}" + else + echo -e "${RED}PostgreSQL service is not running.${NC}" + fi +} + +# Function to check MongoDB installation and service +check_mongo() { + if command -v mongod > /dev/null 2>&1; then + echo -e "${GREEN}MongoDB is installed. Version: $(mongod --version | head -n 1)${NC}" + else + echo -e "${RED}MongoDB is not installed.${NC}" + return + fi + + if systemctl is-active --quiet mongod; then + echo -e "${GREEN}MongoDB service is running.${NC}" + else + echo -e "${RED}MongoDB service is not running.${NC}" + fi +} + +# Function to check if Redis BullMQ is installed (in Node.js context) +check_bullmq() { + if npm list -g | grep -q bullmq; then + echo -e "${GREEN}Redis BullMQ is installed globally.${NC}" + else + echo -e "${RED}Redis BullMQ is not installed globally.${NC}" + fi +} + +# Function to check Gotenberg installation and service status +check_gotenberg() { + if command -v docker > /dev/null 2>&1; then + echo -e "${GREEN}Docker is installed. Version: $(docker --version)${NC}" + else + echo -e "${RED}Docker is not installed.${NC}" + return + fi + + if docker ps | grep -q gotenberg; then + echo -e "${GREEN}Gotenberg Docker container is running.${NC}" + else + echo -e "${RED}Gotenberg Docker container is not running.${NC}" + fi +} + +# Main execution flow of the script +echo "ELEVATE-Project Dependencies Status" + +check_nodejs +check_kafka +check_redis +check_pm2 +check_postgres +check_citus +check_mongo +# check_bullmq +check_gotenberg diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/citus_setup.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/citus_setup.sh new file mode 100644 index 00000000..3e9996ac --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/citus_setup.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +# --- 1. ARGUMENT VALIDATION --- +if [ $# -lt 2 ]; then + echo "Error: Folder name and database URL not provided." >&2 + echo "Usage: $0 " >&2 + exit 1 +fi + +FOLDER_NAME="$1" +DEV_DATABASE_URL="$2" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." >&2 + exit 1 +fi + +# --- 2. HIGHLY RELIABLE DATABASE URL PARSING --- +echo "Parsing database URL..." + +# Remove protocol (postgres://) +DB_CLEAN_URL=$(echo "$DEV_DATABASE_URL" | sed 's/.*:\/\///') + +# Extract DB_NAME +DB_NAME=$(echo "$DB_CLEAN_URL" | awk -F '/' '{print $NF}') + +# Remove DB_NAME from path +HOST_PORT_PATH=$(echo "$DB_CLEAN_URL" | sed "s/\/$DB_NAME//") + +# Extract components +DB_USER=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $1}') +DB_PASSWORD=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $2}') +DB_HOST=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $3}') +DB_PORT=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $4}') + +# Log extracted values (excluding password) +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "" + +if [[ -z "$DB_PORT" ]]; then + echo "Error: Could not extract database port. Check URL format." >&2 + exit 1 +fi + +# --- 3. WAIT FOR LOCAL POSTGRESQL --- + +echo "Waiting for PostgreSQL on $DB_HOST:$DB_PORT to accept connections..." +until pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" > /dev/null 2>&1; do + echo -n "." + sleep 1 +done +echo -e "\nPostgreSQL is ready." + +# Wait until database exists +echo "Checking existence of database '$DB_NAME'..." +until PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -p "$DB_PORT" \ + -d postgres \ + -lqt | awk '{print $1}' | grep -qw "$DB_NAME"; do + echo -n "." + sleep 5 +done +echo -e "\nDatabase '$DB_NAME' exists." + +# --- 4. CITUS EXTENSION SETUP --- + +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." >&2 + exit 1 +fi + +echo "Creating Citus extension (if not exists)..." +PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + --set ON_ERROR_STOP=1 \ + -c "CREATE EXTENSION IF NOT EXISTS citus;" + +# --- 5. EXECUTE SQL FILE WITH ROBUST TABLE CHECK --- + +check_table() { + local table_name=$1 + PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + -q -t \ + --set ON_ERROR_STOP=1 \ + -c "SELECT 1 FROM $table_name LIMIT 1;" \ + > /dev/null 2>&1 +} + +echo "Starting creation of distributed tables..." + +while IFS= read -r line; do + trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + if [[ "$trimmed_line" =~ ^create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Processing table: '$table'" + + # Wait until table exists + until check_table "$table"; do + echo "Table '$table' does not exist yet (waiting for migration)..." + sleep 1 + done + + echo "Table '$table' exists. Applying Citus distribution..." + PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + --set ON_ERROR_STOP=1 \ + -c "$trimmed_line" + fi +done < "$DISTRIBUTION_COLUMNS_FILE" + +echo "โœ… Local PostgreSQL Citus setup and table distribution completed successfully!" diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/create-databases.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/create-databases.sh new file mode 100644 index 00000000..2ce07163 --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/create-databases.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Run commands as the postgres user +sudo -u postgres psql -p 5432 -c "CREATE USER postgres WITH ENCRYPTED PASSWORD 'postgres';" + +# Create the user database and assign privileges +sudo -u postgres psql -p 5432 -c "CREATE DATABASE users;" +sudo -u postgres psql -p 5432 -d users -c "GRANT ALL PRIVILEGES ON DATABASE users TO postgres;" +sudo -u postgres psql -p 5432 -d users -c "GRANT ALL ON SCHEMA public TO postgres;" + +# Create the notification database and assign privileges +sudo -u postgres psql -p 5432 -c "CREATE DATABASE notification;" +sudo -u postgres psql -p 5432 -d notification -c "GRANT ALL PRIVILEGES ON DATABASE notification TO postgres;" +sudo -u postgres psql -p 5432 -d notification -c "GRANT ALL ON SCHEMA public TO postgres;" + +echo "Database setup complete." diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/insert_sample_data.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/insert_sample_data.sh new file mode 100644 index 00000000..fabcff4d --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/insert_sample_data.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# --- 0. PRE-REQUISITE: INSERT MISSING ROLES (for foreign key resolution) --- +# NOTE: Role IDs 1 and 8 are required for subsequent inserts. +# You should verify the tenant_code column and other required fields for user_roles table. +# Assuming the necessary role records (1 and 8) are missing and need to be created first. + +# --- 1. INSERT INTO public.users --- +# These inserts appear correct and should result in 'INSERT 0 1' output. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" + +# --- 2. INSERT INTO public.user_organizations --- +# These inserts should be fine. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + +# --- 3. UPDATE public.tenants --- +# FIX: Changed -d user to -d users +sudo -u postgres psql -p 5432 -d users -c " +UPDATE public.tenants +SET meta = '{ + \"factors\": [\"professional_role\", \"professional_subroles\"], + \"observableEntityKeys\": [\"professional_subroles\"], + \"optional_factors\": [\"state\", \"district\", \"block\", \"cluster\", \"school\"], + \"validationExcludedScopeKeys\": [\"language\", \"gender\"], + \"portalSignInUrl\": \"https://shikshagrah-qa.tekdinext.com/register\" +}' +WHERE code = 'default'; +" + +# --- 4. INSERT INTO public.user_organization_roles --- +# These inserts now occur AFTER the required user_roles (ID 1 and 8) have been added. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 3, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 4, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + + +# --- 5. INSERT INTO public.entity_types --- +# FIX: Added 'tenant_code' to the columns list and provided the value 'default'. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (10, 'professional_role','Professional Role','ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_cod');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (11, 'professional_subroles','Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_cod');" + +# --- 6. Final Commands --- +sudo -u postgres psql -p 5432 -d users -c "SELECT nextval('users_id_seq'::regclass) FROM public.users;" +sudo -u postgres psql -p 5432 -d users -c "SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials;" +sudo -u postgres psql -p 5432 -d users -c "UPDATE role_permission_mapping SET role_title = 'state_education_officer' WHERE role_title = 'mentor';" +sudo -u postgres psql -p 5432 -d users -c "SELECT NULL;" \ No newline at end of file diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/install-dependencies.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/install-dependencies.sh new file mode 100644 index 00000000..f6cf5dd9 --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/install-dependencies.sh @@ -0,0 +1,206 @@ +#!/bin/bash + +echo "Starting the installation script..." + +# Function to install Node.js LTS +install_nodejs() { + echo "Installing Node.js version 20..." + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential +} + + +# Function to install Kafka +install_kafka() { + echo "Installing Kafka..." + sudo DEBIAN_FRONTEND=noninteractive apt install -y openjdk-11-jdk + sudo wget https://archive.apache.org/dist/kafka/3.5.0/kafka_2.12-3.5.0.tgz -O kafka.tgz + sudo tar xzf kafka.tgz -C /opt + sudo mv /opt/kafka_2.12-3.5.0 /opt/kafka + + echo "Creating Zookeeper service..." + sudo bash -c 'cat > /etc/systemd/system/zookeeper.service << EOF +[Unit] +Description=Apache Zookeeper service +Documentation=http://zookeeper.apache.org +Requires=network.target remote-fs.target +After=network.target remote-fs.target + +[Service] +Type=simple +ExecStart=/opt/kafka/bin/zookeeper-server-start.sh /opt/kafka/config/zookeeper.properties +ExecStop=/opt/kafka/bin/zookeeper-server-stop.sh +Restart=on-abnormal + +[Install] +WantedBy=multi-user.target +EOF' + + echo "Creating Kafka service..." + sudo bash -c 'cat > /etc/systemd/system/kafka.service << EOF +[Unit] +Description=Apache Kafka Service +Documentation=http://kafka.apache.org/documentation.html +Requires=zookeeper.service + +[Service] +Type=simple +Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64" +ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties +ExecStop=/opt/kafka/bin/kafka-server-stop.sh + +[Install] +WantedBy=multi-user.target +EOF' + + sudo systemctl daemon-reload + sudo systemctl start zookeeper + sudo systemctl start kafka +} + +# Function to install Redis +install_redis() { + echo "Installing Redis..." + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y redis-server + sudo sed -i 's/^# *supervised .*/supervised systemd/' /etc/redis/redis.conf + sudo systemctl restart redis.service +} + +# Function to install Redis BullMQ (as a global Node.js package) +install_bullmq() { + echo "Installing Redis BullMQ..." + sudo npm install -g bullmq + echo "Redis BullMQ has been installed globally." +} + +# Function to install Citus +install_citus() { + echo "Installing Citus..." + + # Ensure the 'postgres' user exists + if ! id "postgres" &>/dev/null; then + echo "Creating postgres user..." + sudo useradd -m -s /bin/bash postgres + echo "postgres user created." + else + echo "postgres user already exists." + fi + + # Download and install the Citus repository setup script + curl https://install.citusdata.com/community/deb.sh | sudo bash + + # Install Citus along with PostgreSQL + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-16-citus-12.1 + + # Switch to the postgres user + sudo su - postgres <> ~/citus/postgresql.conf + + # Start the Citus server + pg_ctl -D ~/citus -o "-p 9700" -l ~/citus_logfile start + + # Create the Citus extension + psql -p 9700 -c "CREATE EXTENSION citus;" + + # Check the Citus version + PSQL_OUTPUT=\$(psql -p 9700 -c "select citus_version();") + echo "\$PSQL_OUTPUT" + +EOF +} + +# Function to install PM2 +install_pm2() { + echo "Installing PM2..." + sudo npm install pm2@latest -g +} + +# Function to install MongoDB +install_mongo() { + echo "Installing MongoDB 4.4.14..." + + # Import MongoDB public GPG key + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - + + # Create the MongoDB source list for Ubuntu (MongoDB 4.4) + echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list + + # Update apt and install MongoDB version 4.4.14 + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y mongodb-org=4.4.14 mongodb-org-server=4.4.14 mongodb-org-shell=4.4.14 mongodb-org-mongos=4.4.14 mongodb-org-tools=4.4.14 + + # Start and enable MongoDB service + sudo systemctl start mongod + sudo systemctl enable mongod + echo "MongoDB 4.4.14 has been installed and started." +} + + +# Function to install Gotenberg (via Docker) +install_gotenberg() { + echo "Installing Docker (required for Gotenberg)..." + + # Install Docker + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y docker.io + + # Start and enable Docker service + sudo systemctl start docker + sudo systemctl enable docker + + echo "Docker installed. Pulling Gotenberg Docker image..." + + # Pull and run Gotenberg Docker container + sudo docker pull gotenberg/gotenberg:7 + sudo docker run -d --name gotenberg -p 3000:3000 gotenberg/gotenberg:7 + + echo "Gotenberg has been installed and started on port 3000." +} + +# Function to display options +display_menu() { + echo "Please select an installation option:" + options=("Install Node.js" "Install Kafka" "Install Redis" "Install Citus" "Install PM2" "Install MongoDB" "Install Gotenberg" "Exit") + for i in ${!options[@]}; do + echo "$((i+1)). ${options[i]}" + done +} + +# Main menu +display_menu + +while true; do + read -p "Enter your choice (1-${#options[@]}): " choice + if (( choice > 0 && choice <= ${#options[@]} )); then + case $choice in + 1) install_nodejs ;; + 2) install_kafka ;; + 3) install_redis ;; + 4) install_citus ;; + 5) install_pm2 ;; + 6) install_mongo ;; + 7) install_gotenberg ;; + 8) echo "Exiting the installation script."; break ;; + *) echo "Invalid option. Please try again." ;; + esac + echo "Operation completed. Here are the next options:" + display_menu + else + echo "Invalid option. Please try again." + fi +done + +echo "Installation script completed." diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/project_entity_sample_data.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/project_entity_sample_data.sh new file mode 100644 index 00000000..96313481 --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/project_entity_sample_data.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# ---------------------------------------------------------------------- +# ELEVATE Project Data Setup Script +# +# This script performs the following actions: +# 1. Downloads sample data files from the ELEVATE-Project GitHub repository. +# 2. Installs the 'mongoose' package (required to run the sample scripts). +# 3. Executes the sample data insertion script using Node.js. +# ---------------------------------------------------------------------- + +# Exit immediately if a command exits with a non-zero status (ensures script stops on download failure) +set -e + +echo "Starting data setup script..." + +# --- 1. Define URL and Files --- +BASE_URL="https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/native/project-with-survey" + +ENTITY_FILE="entity_sampleData.js" +PROJECT_FILE="project_sampleData.js" +SURVEY_FILE="survey_sampleData.js" +INSERT_SCRIPT="insert_sample_solutions.js" + +# --- 2. Download Files --- +echo "1. Downloading sample data files..." + +# Download entity_sampleData.js +curl -L "${BASE_URL}/${ENTITY_FILE}" -o "${ENTITY_FILE}" +echo "Downloaded ${ENTITY_FILE}" + +# Download project_sampleData.js +curl -L "${BASE_URL}/${PROJECT_FILE}" -o "${PROJECT_FILE}" +echo "Downloaded ${PROJECT_FILE}" + +# Download survey_sampleData.js +curl -L "${BASE_URL}/${SURVEY_FILE}" -o "${SURVEY_FILE}" +echo "Downloaded ${SURVEY_FILE}" + +# Download insert_sample_solutions.js (saved correctly to be run by node) +curl -L "${BASE_URL}/${INSERT_SCRIPT}" -o "${INSERT_SCRIPT}" +echo "Downloaded ${INSERT_SCRIPT}" + +# NOTE on Original Request: If you need to populate 'user/src/.env' with a specific file, +# you would add another 'curl' command here, but the file you linked was a JS script. + +echo "" +echo "2. Installing required Node packages (mongoose, mongodb)..." + +# Initialize a package.json file if one doesn't exist to prevent climbing up the directory tree +if [ ! -f "package.json" ]; then + npm init -y > /dev/null +fi +npm install mongoose +npm install mongodb + +# --- 4. Run Insertion Script --- +echo "" +echo "3. Running the sample data insertion script..." +node "${INSERT_SCRIPT}" + +echo "" +echo "--- Data setup complete! ---" \ No newline at end of file diff --git a/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/uninstall-dependencies.sh b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/uninstall-dependencies.sh new file mode 100644 index 00000000..c14a313a --- /dev/null +++ b/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/uninstall-dependencies.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# Define color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Function to show the menu +show_menu() { + echo -e "${GREEN}Please choose an option to uninstall:${NC}" + echo "1) PM2" + echo "2) Node.js and npm" + echo "3) Kafka and Zookeeper" + echo "4) Redis" + echo "5) MongoDB" + echo "6) Citus and PostgreSQL" + echo "7) Gotenberg" + echo "8) Exit" + echo -e "${GREEN}Enter your choice [1-8]: ${NC}" +} + +# Function to uninstall PM2 +uninstall_pm2() { + echo -e "${RED}Uninstalling PM2...${NC}" + sudo npm uninstall -g pm2 +} + +# Function to uninstall Node.js and npm +uninstall_nodejs() { + echo -e "${RED}Uninstalling Node.js and npm...${NC}" + sudo apt-get remove -y nodejs + sudo apt-get purge -y nodejs + sudo apt-get autoremove -y +} + +# Function to uninstall Kafka and Zookeeper +uninstall_kafka_zookeeper() { + echo -e "${RED}Removing Kafka and Zookeeper...${NC}" + sudo systemctl stop kafka + sudo systemctl disable kafka + sudo systemctl stop zookeeper + sudo systemctl disable zookeeper + sudo rm /etc/systemd/system/kafka.service + sudo rm /etc/systemd/system/zookeeper.service + sudo rm -rf /opt/kafka + sudo systemctl daemon-reload +} + +# Function to uninstall Redis +uninstall_redis() { + echo -e "${RED}Uninstalling Redis...${NC}" + sudo systemctl stop redis + sudo systemctl disable redis + sudo apt-get remove -y redis-server + sudo apt-get purge -y redis-server + sudo apt-get autoremove -y +} + +# Function to uninstall Redis BullMQ +uninstall_bullmq() { + echo -e "${RED}Uninstalling Redis BullMQ...${NC}" + sudo npm uninstall -g bullmq + echo -e "${GREEN}Redis BullMQ has been uninstalled.${NC}" +} + +# Function to uninstall MongoDB +uninstall_mongodb() { + echo -e "${RED}Uninstalling MongoDB...${NC}" + sudo systemctl stop mongod + sudo systemctl disable mongod + sudo apt-get remove -y mongodb-org + sudo apt-get purge -y mongodb-org + sudo apt-get autoremove -y + sudo rm -rf /var/log/mongodb + sudo rm -rf /var/lib/mongodb + sudo rm /etc/apt/sources.list.d/mongodb-org-*.list + echo -e "${GREEN}MongoDB has been uninstalled.${NC}" +} + +# Function to uninstall Citus and PostgreSQL +uninstall_citus_postgresql() { + echo -e "${RED}Uninstalling Citus and PostgreSQL...${NC}" + sudo su - postgres -c "pg_ctl -D ~/citus stop" + sudo apt-get remove -y postgresql-16-citus-12.1 + sudo apt-get purge -y postgresql-16-citus-12.1 + sudo apt-get remove -y postgresql* + sudo apt-get purge -y postgresql* + sudo apt-get autoremove -y + sudo pkill -u postgres + sudo deluser --remove-home postgres +} + +# Function to uninstall Gotenberg +uninstall_gotenberg() { + echo -e "${RED}Uninstalling Gotenberg...${NC}" + + # Stop and remove the Gotenberg Docker container + sudo docker stop gotenberg + sudo docker rm gotenberg + + # Optionally uninstall Docker (if it's no longer needed) + echo -e "${GREEN}Do you also want to uninstall Docker? (y/n)${NC}" + read uninstall_docker + if [[ "$uninstall_docker" == "y" || "$uninstall_docker" == "Y" ]]; then + echo -e "${RED}Uninstalling Docker...${NC}" + sudo apt-get remove -y docker.io + sudo apt-get purge -y docker.io + sudo apt-get autoremove -y + sudo rm -rf /var/lib/docker + echo -e "${GREEN}Docker has been uninstalled.${NC}" + fi + echo -e "${GREEN}Gotenberg has been uninstalled.${NC}" +} + +# Main loop +while true; do + show_menu + read choice + case $choice in + 1) uninstall_pm2 ;; + 2) uninstall_nodejs ;; + 3) uninstall_kafka_zookeeper ;; + 4) uninstall_redis ;; + 5) uninstall_mongodb ;; + 6) uninstall_citus_postgresql ;; + 7) uninstall_gotenberg ;; + 8) echo -e "${GREEN}Exiting uninstallation process.${NC}"; exit ;; + *) echo -e "${RED}Invalid option, please try again.${NC}" ;; + esac + echo -e "${GREEN}Operation completed.${NC}" +done diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/check-dependencies.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/check-dependencies.sh new file mode 100644 index 00000000..98ff5e8b --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/check-dependencies.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +# Define ANSI color codes for output formatting +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Function to check Node.js installation +check_nodejs() { + if command -v node > /dev/null 2>&1; then + echo -e "${GREEN}Node.js is installed. Version: $(node --version)${NC}" + else + echo -e "${RED}Node.js is not installed.${NC}" + fi +} + +# Function to check Apache Kafka and Zookeeper installation +check_kafka() { + if [ -d "/opt/kafka" ]; then + echo -e "${GREEN}Kafka directory exists.${NC}" + else + echo -e "${RED}Kafka directory does not exist.${NC}" + fi + + if systemctl is-active --quiet zookeeper; then + echo -e "${GREEN}Zookeeper service is running.${NC}" + else + echo -e "${RED}Zookeeper service is not running.${NC}" + fi + + if systemctl is-active --quiet kafka; then + echo -e "${GREEN}Kafka service is running.${NC}" + else + echo -e "${RED}Kafka service is not running.${NC}" + fi +} + +# Function to check Redis installation and service status +check_redis() { + if command -v redis-server > /dev/null 2>&1; then + echo -e "${GREEN}Redis server is installed. Version: $(redis-server --version)${NC}" + else + echo -e "${RED}Redis server is not installed.${NC}" + return + fi + + if systemctl status redis-server.service &> /dev/null; then + echo -e "${GREEN}Redis service is running.${NC}" + else + echo -e "${RED}Redis service is not running or inactive.${NC}" + fi +} + +# Function to check Citus installation +check_citus() { + if sudo su - postgres -c "psql -p 9700 -c 'SELECT citus_version();'" &> /dev/null; then + echo -e "${GREEN}Citus is running on port 9700.${NC}" + else + echo -e "${RED}Citus is not running or not installed.${NC}" + fi +} + +# Function to check PM2 installation +check_pm2() { + if command -v pm2 > /dev/null 2>&1; then + echo -e "${GREEN}PM2 is installed. Version: $(pm2 -v)${NC}" + else + echo -e "${RED}PM2 is not installed.${NC}" + fi +} + +# Function to check PostgreSQL installation and service +check_postgres() { + if command -v psql > /dev/null 2>&1; then + echo -e "${GREEN}PostgreSQL is installed. Version: $(psql --version)${NC}" + else + echo -e "${RED}PostgreSQL is not installed.${NC}" + fi + + if systemctl is-active --quiet postgresql; then + echo -e "${GREEN}PostgreSQL service is running.${NC}" + else + echo -e "${RED}PostgreSQL service is not running.${NC}" + fi +} + +# Function to check MongoDB installation and service +check_mongo() { + if command -v mongod > /dev/null 2>&1; then + echo -e "${GREEN}MongoDB is installed. Version: $(mongod --version | head -n 1)${NC}" + else + echo -e "${RED}MongoDB is not installed.${NC}" + return + fi + + if systemctl is-active --quiet mongod; then + echo -e "${GREEN}MongoDB service is running.${NC}" + else + echo -e "${RED}MongoDB service is not running.${NC}" + fi +} + +# Function to check if Redis BullMQ is installed (in Node.js context) +check_bullmq() { + if npm list -g | grep -q bullmq; then + echo -e "${GREEN}Redis BullMQ is installed globally.${NC}" + else + echo -e "${RED}Redis BullMQ is not installed globally.${NC}" + fi +} + +# Function to check Gotenberg installation and service status +check_gotenberg() { + if command -v docker > /dev/null 2>&1; then + echo -e "${GREEN}Docker is installed. Version: $(docker --version)${NC}" + else + echo -e "${RED}Docker is not installed.${NC}" + return + fi + + if docker ps | grep -q gotenberg; then + echo -e "${GREEN}Gotenberg Docker container is running.${NC}" + else + echo -e "${RED}Gotenberg Docker container is not running.${NC}" + fi +} + +# Main execution flow of the script +echo "ELEVATE-Project Dependencies Status" + +check_nodejs +check_kafka +check_redis +check_pm2 +check_postgres +check_citus +check_mongo +# check_bullmq +check_gotenberg diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/citus_setup.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/citus_setup.sh new file mode 100644 index 00000000..3e9996ac --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/citus_setup.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -e + +# --- 1. ARGUMENT VALIDATION --- +if [ $# -lt 2 ]; then + echo "Error: Folder name and database URL not provided." >&2 + echo "Usage: $0 " >&2 + exit 1 +fi + +FOLDER_NAME="$1" +DEV_DATABASE_URL="$2" + +# Check if folder exists +if [ ! -d "$FOLDER_NAME" ]; then + echo "Error: Folder '$FOLDER_NAME' not found." >&2 + exit 1 +fi + +# --- 2. HIGHLY RELIABLE DATABASE URL PARSING --- +echo "Parsing database URL..." + +# Remove protocol (postgres://) +DB_CLEAN_URL=$(echo "$DEV_DATABASE_URL" | sed 's/.*:\/\///') + +# Extract DB_NAME +DB_NAME=$(echo "$DB_CLEAN_URL" | awk -F '/' '{print $NF}') + +# Remove DB_NAME from path +HOST_PORT_PATH=$(echo "$DB_CLEAN_URL" | sed "s/\/$DB_NAME//") + +# Extract components +DB_USER=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $1}') +DB_PASSWORD=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $2}') +DB_HOST=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $3}') +DB_PORT=$(echo "$HOST_PORT_PATH" | awk -F '[:@]' '{print $4}') + +# Log extracted values (excluding password) +echo "Extracted Database Variables:" +echo "DB_USER: $DB_USER" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "" + +if [[ -z "$DB_PORT" ]]; then + echo "Error: Could not extract database port. Check URL format." >&2 + exit 1 +fi + +# --- 3. WAIT FOR LOCAL POSTGRESQL --- + +echo "Waiting for PostgreSQL on $DB_HOST:$DB_PORT to accept connections..." +until pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" > /dev/null 2>&1; do + echo -n "." + sleep 1 +done +echo -e "\nPostgreSQL is ready." + +# Wait until database exists +echo "Checking existence of database '$DB_NAME'..." +until PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -p "$DB_PORT" \ + -d postgres \ + -lqt | awk '{print $1}' | grep -qw "$DB_NAME"; do + echo -n "." + sleep 5 +done +echo -e "\nDatabase '$DB_NAME' exists." + +# --- 4. CITUS EXTENSION SETUP --- + +DISTRIBUTION_COLUMNS_FILE="$FOLDER_NAME/distributionColumns.sql" +if [ ! -f "$DISTRIBUTION_COLUMNS_FILE" ]; then + echo "Error: distributionColumns.sql not found in folder '$FOLDER_NAME'." >&2 + exit 1 +fi + +echo "Creating Citus extension (if not exists)..." +PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + --set ON_ERROR_STOP=1 \ + -c "CREATE EXTENSION IF NOT EXISTS citus;" + +# --- 5. EXECUTE SQL FILE WITH ROBUST TABLE CHECK --- + +check_table() { + local table_name=$1 + PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + -q -t \ + --set ON_ERROR_STOP=1 \ + -c "SELECT 1 FROM $table_name LIMIT 1;" \ + > /dev/null 2>&1 +} + +echo "Starting creation of distributed tables..." + +while IFS= read -r line; do + trimmed_line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + + if [[ "$trimmed_line" =~ ^create_distributed_table\(\'([^\']+)\', ]]; then + table="${BASH_REMATCH[1]}" + echo "Processing table: '$table'" + + # Wait until table exists + until check_table "$table"; do + echo "Table '$table' does not exist yet (waiting for migration)..." + sleep 1 + done + + echo "Table '$table' exists. Applying Citus distribution..." + PGPASSWORD="$DB_PASSWORD" psql \ + -h "$DB_HOST" \ + -U "$DB_USER" \ + -d "$DB_NAME" \ + -p "$DB_PORT" \ + --set ON_ERROR_STOP=1 \ + -c "$trimmed_line" + fi +done < "$DISTRIBUTION_COLUMNS_FILE" + +echo "โœ… Local PostgreSQL Citus setup and table distribution completed successfully!" diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/create-databases.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/create-databases.sh new file mode 100644 index 00000000..2ce07163 --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/create-databases.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Run commands as the postgres user +sudo -u postgres psql -p 5432 -c "CREATE USER postgres WITH ENCRYPTED PASSWORD 'postgres';" + +# Create the user database and assign privileges +sudo -u postgres psql -p 5432 -c "CREATE DATABASE users;" +sudo -u postgres psql -p 5432 -d users -c "GRANT ALL PRIVILEGES ON DATABASE users TO postgres;" +sudo -u postgres psql -p 5432 -d users -c "GRANT ALL ON SCHEMA public TO postgres;" + +# Create the notification database and assign privileges +sudo -u postgres psql -p 5432 -c "CREATE DATABASE notification;" +sudo -u postgres psql -p 5432 -d notification -c "GRANT ALL PRIVILEGES ON DATABASE notification TO postgres;" +sudo -u postgres psql -p 5432 -d notification -c "GRANT ALL ON SCHEMA public TO postgres;" + +echo "Database setup complete." diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/insert_sample_data.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/insert_sample_data.sh new file mode 100644 index 00000000..fabcff4d --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/insert_sample_data.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# --- 0. PRE-REQUISITE: INSERT MISSING ROLES (for foreign key resolution) --- +# NOTE: Role IDs 1 and 8 are required for subsequent inserts. +# You should verify the tenant_code column and other required fields for user_roles table. +# Assuming the necessary role records (1 and 8) are missing and need to be created first. + +# --- 1. INSERT INTO public.users --- +# These inserts appear correct and should result in 'INSERT 0 1' output. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default',NULL,NULL, NULL);" + +# --- 2. INSERT INTO public.user_organizations --- +# These inserts should be fine. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + +# --- 3. UPDATE public.tenants --- +# FIX: Changed -d user to -d users +sudo -u postgres psql -p 5432 -d users -c " +UPDATE public.tenants +SET meta = '{ + \"factors\": [\"professional_role\", \"professional_subroles\"], + \"observableEntityKeys\": [\"professional_subroles\"], + \"optional_factors\": [\"state\", \"district\", \"block\", \"cluster\", \"school\"], + \"validationExcludedScopeKeys\": [\"language\", \"gender\"], + \"portalSignInUrl\": \"https://shikshagrah-qa.tekdinext.com/register\" +}' +WHERE code = 'default'; +" + +# --- 4. INSERT INTO public.user_organization_roles --- +# These inserts now occur AFTER the required user_roles (ID 1 and 8) have been added. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 3, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 4, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL);" + + +# --- 5. INSERT INTO public.entity_types --- +# FIX: Added 'tenant_code' to the columns list and provided the value 'default'. +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (6, 'block', 'Block', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (7, 'school', 'School', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (8, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (9, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (10, 'professional_role','Professional Role','ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_cod');" +sudo -u postgres psql -p 5432 -d users -c "INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (11, 'professional_subroles','Professional Subroles', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_cod');" + +# --- 6. Final Commands --- +sudo -u postgres psql -p 5432 -d users -c "SELECT nextval('users_id_seq'::regclass) FROM public.users;" +sudo -u postgres psql -p 5432 -d users -c "SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials;" +sudo -u postgres psql -p 5432 -d users -c "UPDATE role_permission_mapping SET role_title = 'state_education_officer' WHERE role_title = 'mentor';" +sudo -u postgres psql -p 5432 -d users -c "SELECT NULL;" \ No newline at end of file diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/install-dependencies.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/install-dependencies.sh new file mode 100644 index 00000000..f6cf5dd9 --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/install-dependencies.sh @@ -0,0 +1,206 @@ +#!/bin/bash + +echo "Starting the installation script..." + +# Function to install Node.js LTS +install_nodejs() { + echo "Installing Node.js version 20..." + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential +} + + +# Function to install Kafka +install_kafka() { + echo "Installing Kafka..." + sudo DEBIAN_FRONTEND=noninteractive apt install -y openjdk-11-jdk + sudo wget https://archive.apache.org/dist/kafka/3.5.0/kafka_2.12-3.5.0.tgz -O kafka.tgz + sudo tar xzf kafka.tgz -C /opt + sudo mv /opt/kafka_2.12-3.5.0 /opt/kafka + + echo "Creating Zookeeper service..." + sudo bash -c 'cat > /etc/systemd/system/zookeeper.service << EOF +[Unit] +Description=Apache Zookeeper service +Documentation=http://zookeeper.apache.org +Requires=network.target remote-fs.target +After=network.target remote-fs.target + +[Service] +Type=simple +ExecStart=/opt/kafka/bin/zookeeper-server-start.sh /opt/kafka/config/zookeeper.properties +ExecStop=/opt/kafka/bin/zookeeper-server-stop.sh +Restart=on-abnormal + +[Install] +WantedBy=multi-user.target +EOF' + + echo "Creating Kafka service..." + sudo bash -c 'cat > /etc/systemd/system/kafka.service << EOF +[Unit] +Description=Apache Kafka Service +Documentation=http://kafka.apache.org/documentation.html +Requires=zookeeper.service + +[Service] +Type=simple +Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64" +ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties +ExecStop=/opt/kafka/bin/kafka-server-stop.sh + +[Install] +WantedBy=multi-user.target +EOF' + + sudo systemctl daemon-reload + sudo systemctl start zookeeper + sudo systemctl start kafka +} + +# Function to install Redis +install_redis() { + echo "Installing Redis..." + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y redis-server + sudo sed -i 's/^# *supervised .*/supervised systemd/' /etc/redis/redis.conf + sudo systemctl restart redis.service +} + +# Function to install Redis BullMQ (as a global Node.js package) +install_bullmq() { + echo "Installing Redis BullMQ..." + sudo npm install -g bullmq + echo "Redis BullMQ has been installed globally." +} + +# Function to install Citus +install_citus() { + echo "Installing Citus..." + + # Ensure the 'postgres' user exists + if ! id "postgres" &>/dev/null; then + echo "Creating postgres user..." + sudo useradd -m -s /bin/bash postgres + echo "postgres user created." + else + echo "postgres user already exists." + fi + + # Download and install the Citus repository setup script + curl https://install.citusdata.com/community/deb.sh | sudo bash + + # Install Citus along with PostgreSQL + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-16-citus-12.1 + + # Switch to the postgres user + sudo su - postgres <> ~/citus/postgresql.conf + + # Start the Citus server + pg_ctl -D ~/citus -o "-p 9700" -l ~/citus_logfile start + + # Create the Citus extension + psql -p 9700 -c "CREATE EXTENSION citus;" + + # Check the Citus version + PSQL_OUTPUT=\$(psql -p 9700 -c "select citus_version();") + echo "\$PSQL_OUTPUT" + +EOF +} + +# Function to install PM2 +install_pm2() { + echo "Installing PM2..." + sudo npm install pm2@latest -g +} + +# Function to install MongoDB +install_mongo() { + echo "Installing MongoDB 4.4.14..." + + # Import MongoDB public GPG key + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - + + # Create the MongoDB source list for Ubuntu (MongoDB 4.4) + echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list + + # Update apt and install MongoDB version 4.4.14 + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y mongodb-org=4.4.14 mongodb-org-server=4.4.14 mongodb-org-shell=4.4.14 mongodb-org-mongos=4.4.14 mongodb-org-tools=4.4.14 + + # Start and enable MongoDB service + sudo systemctl start mongod + sudo systemctl enable mongod + echo "MongoDB 4.4.14 has been installed and started." +} + + +# Function to install Gotenberg (via Docker) +install_gotenberg() { + echo "Installing Docker (required for Gotenberg)..." + + # Install Docker + sudo apt update + sudo DEBIAN_FRONTEND=noninteractive apt install -y docker.io + + # Start and enable Docker service + sudo systemctl start docker + sudo systemctl enable docker + + echo "Docker installed. Pulling Gotenberg Docker image..." + + # Pull and run Gotenberg Docker container + sudo docker pull gotenberg/gotenberg:7 + sudo docker run -d --name gotenberg -p 3000:3000 gotenberg/gotenberg:7 + + echo "Gotenberg has been installed and started on port 3000." +} + +# Function to display options +display_menu() { + echo "Please select an installation option:" + options=("Install Node.js" "Install Kafka" "Install Redis" "Install Citus" "Install PM2" "Install MongoDB" "Install Gotenberg" "Exit") + for i in ${!options[@]}; do + echo "$((i+1)). ${options[i]}" + done +} + +# Main menu +display_menu + +while true; do + read -p "Enter your choice (1-${#options[@]}): " choice + if (( choice > 0 && choice <= ${#options[@]} )); then + case $choice in + 1) install_nodejs ;; + 2) install_kafka ;; + 3) install_redis ;; + 4) install_citus ;; + 5) install_pm2 ;; + 6) install_mongo ;; + 7) install_gotenberg ;; + 8) echo "Exiting the installation script."; break ;; + *) echo "Invalid option. Please try again." ;; + esac + echo "Operation completed. Here are the next options:" + display_menu + else + echo "Invalid option. Please try again." + fi +done + +echo "Installation script completed." diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/project_entity_sample_data.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/project_entity_sample_data.sh new file mode 100644 index 00000000..3d0ff8d8 --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/project_entity_sample_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# ---------------------------------------------------------------------- +# ELEVATE Project Data Setup Script +# +# This script performs the following actions: +# 1. Downloads sample data files from the ELEVATE-Project GitHub repository. +# 2. Installs the 'mongoose' package (required to run the sample scripts). +# 3. Executes the sample data insertion script using Node.js. +# ---------------------------------------------------------------------- + +# Exit immediately if a command exits with a non-zero status (ensures script stops on download failure) +set -e + +echo "Starting data setup script..." + +# --- 1. Define URL and Files --- +BASE_URL="https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/native/stand-alone" + +ENTITY_FILE="entity_sampleData.js" +PROJECT_FILE="project_sampleData.js" +INSERT_SCRIPT="insert_sample_solutions.js" + +# --- 2. Download Files --- +echo "1. Downloading sample data files..." + +# Download entity_sampleData.js +curl -L "${BASE_URL}/${ENTITY_FILE}" -o "${ENTITY_FILE}" +echo "Downloaded ${ENTITY_FILE}" + +# Download project_sampleData.js +curl -L "${BASE_URL}/${PROJECT_FILE}" -o "${PROJECT_FILE}" +echo "Downloaded ${PROJECT_FILE}" + +# Download insert_sample_solutions.js (saved correctly to be run by node) +curl -L "${BASE_URL}/${INSERT_SCRIPT}" -o "${INSERT_SCRIPT}" +echo "Downloaded ${INSERT_SCRIPT}" + +# NOTE on Original Request: If you need to populate 'user/src/.env' with a specific file, +# you would add another 'curl' command here, but the file you linked was a JS script. + +echo "" +echo "2. Installing required Node packages (mongoose, mongodb)..." + +# Initialize a package.json file if one doesn't exist to prevent climbing up the directory tree +if [ ! -f "package.json" ]; then + npm init -y > /dev/null +fi +npm install mongoose +npm install mongodb + +# --- 4. Run Insertion Script --- +echo "" +echo "3. Running the sample data insertion script..." +node "${INSERT_SCRIPT}" + +echo "" +echo "--- Data setup complete! ---" \ No newline at end of file diff --git a/documentation/3.4.0/native/scripts/stand-alone/ubuntu/uninstall-dependencies.sh b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/uninstall-dependencies.sh new file mode 100644 index 00000000..c14a313a --- /dev/null +++ b/documentation/3.4.0/native/scripts/stand-alone/ubuntu/uninstall-dependencies.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +# Define color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Function to show the menu +show_menu() { + echo -e "${GREEN}Please choose an option to uninstall:${NC}" + echo "1) PM2" + echo "2) Node.js and npm" + echo "3) Kafka and Zookeeper" + echo "4) Redis" + echo "5) MongoDB" + echo "6) Citus and PostgreSQL" + echo "7) Gotenberg" + echo "8) Exit" + echo -e "${GREEN}Enter your choice [1-8]: ${NC}" +} + +# Function to uninstall PM2 +uninstall_pm2() { + echo -e "${RED}Uninstalling PM2...${NC}" + sudo npm uninstall -g pm2 +} + +# Function to uninstall Node.js and npm +uninstall_nodejs() { + echo -e "${RED}Uninstalling Node.js and npm...${NC}" + sudo apt-get remove -y nodejs + sudo apt-get purge -y nodejs + sudo apt-get autoremove -y +} + +# Function to uninstall Kafka and Zookeeper +uninstall_kafka_zookeeper() { + echo -e "${RED}Removing Kafka and Zookeeper...${NC}" + sudo systemctl stop kafka + sudo systemctl disable kafka + sudo systemctl stop zookeeper + sudo systemctl disable zookeeper + sudo rm /etc/systemd/system/kafka.service + sudo rm /etc/systemd/system/zookeeper.service + sudo rm -rf /opt/kafka + sudo systemctl daemon-reload +} + +# Function to uninstall Redis +uninstall_redis() { + echo -e "${RED}Uninstalling Redis...${NC}" + sudo systemctl stop redis + sudo systemctl disable redis + sudo apt-get remove -y redis-server + sudo apt-get purge -y redis-server + sudo apt-get autoremove -y +} + +# Function to uninstall Redis BullMQ +uninstall_bullmq() { + echo -e "${RED}Uninstalling Redis BullMQ...${NC}" + sudo npm uninstall -g bullmq + echo -e "${GREEN}Redis BullMQ has been uninstalled.${NC}" +} + +# Function to uninstall MongoDB +uninstall_mongodb() { + echo -e "${RED}Uninstalling MongoDB...${NC}" + sudo systemctl stop mongod + sudo systemctl disable mongod + sudo apt-get remove -y mongodb-org + sudo apt-get purge -y mongodb-org + sudo apt-get autoremove -y + sudo rm -rf /var/log/mongodb + sudo rm -rf /var/lib/mongodb + sudo rm /etc/apt/sources.list.d/mongodb-org-*.list + echo -e "${GREEN}MongoDB has been uninstalled.${NC}" +} + +# Function to uninstall Citus and PostgreSQL +uninstall_citus_postgresql() { + echo -e "${RED}Uninstalling Citus and PostgreSQL...${NC}" + sudo su - postgres -c "pg_ctl -D ~/citus stop" + sudo apt-get remove -y postgresql-16-citus-12.1 + sudo apt-get purge -y postgresql-16-citus-12.1 + sudo apt-get remove -y postgresql* + sudo apt-get purge -y postgresql* + sudo apt-get autoremove -y + sudo pkill -u postgres + sudo deluser --remove-home postgres +} + +# Function to uninstall Gotenberg +uninstall_gotenberg() { + echo -e "${RED}Uninstalling Gotenberg...${NC}" + + # Stop and remove the Gotenberg Docker container + sudo docker stop gotenberg + sudo docker rm gotenberg + + # Optionally uninstall Docker (if it's no longer needed) + echo -e "${GREEN}Do you also want to uninstall Docker? (y/n)${NC}" + read uninstall_docker + if [[ "$uninstall_docker" == "y" || "$uninstall_docker" == "Y" ]]; then + echo -e "${RED}Uninstalling Docker...${NC}" + sudo apt-get remove -y docker.io + sudo apt-get purge -y docker.io + sudo apt-get autoremove -y + sudo rm -rf /var/lib/docker + echo -e "${GREEN}Docker has been uninstalled.${NC}" + fi + echo -e "${GREEN}Gotenberg has been uninstalled.${NC}" +} + +# Main loop +while true; do + show_menu + read choice + case $choice in + 1) uninstall_pm2 ;; + 2) uninstall_nodejs ;; + 3) uninstall_kafka_zookeeper ;; + 4) uninstall_redis ;; + 5) uninstall_mongodb ;; + 6) uninstall_citus_postgresql ;; + 7) uninstall_gotenberg ;; + 8) echo -e "${GREEN}Exiting uninstallation process.${NC}"; exit ;; + *) echo -e "${RED}Invalid option, please try again.${NC}" ;; + esac + echo -e "${GREEN}Operation completed.${NC}" +done diff --git a/documentation/3.4.0/sample-data/mac-linux/user/sampleData.sql b/documentation/3.4.0/sample-data/mac-linux/user/sampleData.sql new file mode 100644 index 00000000..9744d2fe --- /dev/null +++ b/documentation/3.4.0/sample-data/mac-linux/user/sampleData.sql @@ -0,0 +1,23 @@ +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (1, 'Rahul R B', 'a0db5e0a39ee13db7fc5d1309e637f2c', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default','53bc5d0ff0c53bee460c08b8afe087455050dc7529a2f1d4f7319c0da653a7e4','+91', NULL); +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (2, 'Prajwal C S', 'c4113be1bc2cef51981a6ec687302e42fc4f87f4dfac4276584844d9e3e0f5ae', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default','53bc5d0ff0c53bee460c08b8afe087455050dc7529a2f1d4f7319c0da653a767','+91', NULL); +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (3, 'Vishnu V P', '1092be87fd483fce1deba56c8cdefa79bed4f70a4b110fc4e7947c57aacff219', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default','53bc5d0ff0c53bee460c08b8afe087455050dc7529a2f1d4f7319c0da653a7e0','+91', NULL); +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at, tenant_code, phone, phone_code, configs) VALUES (4, 'Mallanagouda R B', 'e5fc674d4b1a54c6cf772485e3bca6f7ae14b60de32b9f0cd9f955ee469345bc', false, '{8,2}', 'ACTIVE', '\$2a\$10\$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL, 'default','53bc5d0ff0c53bee460c08b8afe087455050dc7529a2f1d4f7319c0da653a700','+91', NULL); + +INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (1, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (2, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (3, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organizations (user_id,organization_code, tenant_code, created_at, updated_at, deleted_at) VALUES (4, 'default_code', 'default', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + + +INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 1, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 3, 'default_code', 2, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 2, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); +INSERT INTO public.user_organization_roles (tenant_code, user_id, organization_code,role_id, created_at, updated_at, deleted_at) VALUES ('default', 4, 'default_code', 3, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL); + + +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex, tenant_code,organization_code) VALUES (5, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, '{\"service\": \"entity-management-service\",\"endPoint\": \"v1/entities/find\"}', true, false, NULL,'default', 'default_code'); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (5, 'district', 'District', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +UPDATE public.entity_types SET status = 'INACTIVE' WHERE id = 3; +SELECT nextval('users_id_seq'::regclass) FROM public.users; +SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials; +SELECT NULL; \ No newline at end of file diff --git a/documentation/3.4.0/sample-data/windows/user/sampleData.sql b/documentation/3.4.0/sample-data/windows/user/sampleData.sql new file mode 100644 index 00000000..43a991df --- /dev/null +++ b/documentation/3.4.0/sample-data/windows/user/sampleData.sql @@ -0,0 +1,21 @@ +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, organization_id, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at) VALUES (1, 'Aarav Patel', '8d1f1e11989cf7b739c9daa972c56c5083b46d490f8023a67eb89d28a2b615ef', false, '{8,2}', 'ACTIVE', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL); +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, organization_id, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at) VALUES (2, 'Arunima Reddy', '0f34042735bb359f1c227b4497cf5074b372085830eef69db07dd80789c25dd5', false, '{8,2}', 'ACTIVE', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL); +INSERT INTO public.users (id, name, email, email_verified, roles, status, password, organization_id, has_accepted_terms_and_conditions, about, location, languages, preferred_language, share_link, image, custom_entity_text, meta, created_at, updated_at, deleted_at) VALUES (3, 'Devika Singh', '1e8828f2f98d16ff63a424620f9d582a1de88268414606a0593c73eb5316543c', false, '{8,2}', 'ACTIVE', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, true, NULL, NULL, NULL, 'en', NULL, NULL, NULL, NULL, '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.426+00', NULL); +INSERT INTO public.users_credentials (id, email, password, organization_id, user_id, meta, created_at, updated_at, deleted_at, organization_user_invite_id) VALUES (1, '8d1f1e11989cf7b739c9daa972c56c5083b46d490f8023a67eb89d28a2b615ef', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, 1, NULL, '2024-04-18 08:12:19.407+00', '2024-04-18 08:12:19.407+00', NULL, NULL); +INSERT INTO public.users_credentials (id, email, password, organization_id, user_id, meta, created_at, updated_at, deleted_at, organization_user_invite_id) VALUES (2, '0f34042735bb359f1c227b4497cf5074b372085830eef69db07dd80789c25dd5', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, 2, NULL, '2024-04-18 08:12:19.407+00', '2024-04-18 08:12:19.407+00', NULL, NULL); +INSERT INTO public.users_credentials (id, email, password, organization_id, user_id, meta, created_at, updated_at, deleted_at, organization_user_invite_id) VALUES (3, '1e8828f2f98d16ff63a424620f9d582a1de88268414606a0593c73eb5316543c', '$2a$10$NTzc2CjEbwB4DavjEKU11eqJXJLrODnvAwvXWor9Dz/gXr55Pvyj.', 1, 3, NULL, '2024-04-18 08:12:19.407+00', '2024-04-18 08:12:19.407+00', NULL, NULL); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (4, 'state', 'State', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (5, 'block', 'Block', 'ACTIVE', 0, 0, true, 'ARRAY', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (6, 'school', 'school', 'ACTIVE', 0, 0, true, 'ARRAY', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +INSERT INTO public.entities (id, entity_type_id, value, label, status, type, created_by, updated_by, created_at, updated_at, deleted_at) VALUES (33, 3, 'bangalore','Bangalore' ,'ACTIVE', 'SYSTEM', 0, NULL, '2024-10-08 11:33:03.03+00', '2024-10-08 11:33:03.03+00', NULL); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (7, 'district', 'district', 'ACTIVE', 0, 0, true, 'STRING', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +INSERT INTO public.entity_types (id, value, label, status, created_by, updated_by, allow_filtering, data_type, organization_id, parent_id, has_entities, allow_custom_entities, model_names, created_at, updated_at, deleted_at, meta, external_entity_type, required, regex) VALUES (8, 'cluster', 'Cluster', 'ACTIVE', 0, 0, true, 'ARRAY', 1, NULL, true, true, '{User}', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, NULL, true, false, NULL); +INSERT INTO public.user_roles (id, title, user_type, status, created_at, updated_at, deleted_at, visibility, organization_id, label) VALUES (8, 'state_education_officer', 0, 'ACTIVE', '2024-04-18 08:12:19.394+00', '2024-04-18 08:12:19.394+00', NULL, 'PUBLIC', 1, 'State Education Officer'); +SELECT nextval('users_id_seq'::regclass) FROM public.users; +SELECT nextval('users_credentials_id_seq'::regclass) FROM public.users_credentials; +SELECT nextval('entity_types_id_seq'::regclass) FROM public.entity_types; +SELECT nextval('entities_id_seq'::regclass) FROM public.entities; +SELECT nextval('user_roles_id_seq'::regclass) FROM public.user_roles; +UPDATE role_permission_mapping SET role_title = 'state_education_officer' WHERE role_title = 'mentor' +UPDATE public.entity_types SET status = 'INACTIVE' WHERE id = 3; +SELECT NULL; \ No newline at end of file diff --git a/documentation/3.4.0/setup/docker/project-with-survey/mac-os/README.md b/documentation/3.4.0/setup/docker/project-with-survey/mac-os/README.md new file mode 100644 index 00000000..b986957c --- /dev/null +++ b/documentation/3.4.0/setup/docker/project-with-survey/mac-os/README.md @@ -0,0 +1,261 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - With Samiksha (Mac-Os) + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Mac users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Mac](https://docs.docker.com/desktop/setup/install/mac-install/). To install and use Nodejs in Mac machine, you can follow instructions here: [How To Install Nodejs in Mac](https://nodejs.org/en/download/package-manager). + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for port in 3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569 4301; do + if sudo lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then + echo "Port $port is IN USE" + else + echo "Port $port is available" + fi +done +``` + +1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/mac-os/setup_project.sh \ + && chmod +x setup_project.sh \ + && ./setup_project.sh + ``` + +> Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. + +**General Instructions :** + +1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. +2. All docker containers can be stopped and removed by using below command. + +``` +sudo ./docker-compose-down.sh +``` + +3. All services and dependencies can be started using below command. + +``` +sudo ./docker-compose-up.sh +``` + +**Keep the current terminal session active, and kindly open a new terminal window within the project directory.** + +**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. + + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` + +2. Set up the citus_setup file by following the steps given below. + + 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + + ``` + sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + +## Update Cloud Credentials for Project Service + +To enable full functionalityโ€”including certificate generation, attachment uploads, and report storageโ€”you must configure cloud credentials in the environment files for both services. + +A. Project Service Configuration Path: + ```./project_env + ``` + +B. Samiksha (Survey & Observation) Service Configuration Path: + ```./samiksha_env + ``` + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available [here](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + + + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +docker exec -i citus_master psql -U postgres -d user < insert_sample_data.sql +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + ``` + node insert_sample_solutions.js + ``` + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection +- + Samiksha Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- + +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/docker/project-with-survey/ubuntu/README.md b/documentation/3.4.0/setup/docker/project-with-survey/ubuntu/README.md new file mode 100644 index 00000000..bbe31780 --- /dev/null +++ b/documentation/3.4.0/setup/docker/project-with-survey/ubuntu/README.md @@ -0,0 +1,259 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - With Survey (Ubuntu) + +Expectation: By following these steps, you will establish a unified environment for the Project Service, integrated with the Survey and Observation modules. This setup focuses purely on the backend API infrastructure required to manage data collection and reporting. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Linux users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Linux](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04). To install and use Nodejs in Linux machine, you can follow instructions here: [How To Install Nodejs in Linux](https://nodejs.org/en/download/package-manager). + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for port in 3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569 4301; do + if sudo lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then + echo "Port $port is IN USE" + else + echo "Port $port is available" + fi +done +``` + +1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/ubuntu/setup_project.sh && chmod +x setup_project.sh && sudo ./setup_project.sh + ``` + +> Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. + +**General Instructions :** + +1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. +2. All docker containers can be stopped and removed by using below command. + +``` +sudo ./docker-compose-down.sh +``` + +3. All services and dependencies can be started using below command. + +``` +sudo ./docker-compose-up.sh +``` + +**Keep the current terminal session active, and kindly open a new terminal window within the project directory.** + +**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. (Skip this for linux) + + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` + +2. Set up the citus_setup file by following the steps given below. + + 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + + ``` + sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + + +## Update Cloud Credentials for Project Service + +To enable full functionalityโ€”including certificate generation, attachment uploads, and report storageโ€”you must configure cloud credentials in the environment files for both services. + +A. Project Service Configuration Path: + ```./project_env + ``` + +B. Samiksha (Survey & Observation) Service Configuration Path: + ```./samiksha_env + ``` + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +sudo chmod +x ./insert_sample_data.sh && sudo ./insert_sample_data.sh user postgres://postgres:postgres@citus_master:5432/user +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +## Sample Data Creation For Projects and Survey + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + ``` + node insert_sample_solutions.js + ``` + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) +- **Observtaion/Survey Portal:** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-portal/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection +- + Samiksha Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/docker/project-with-survey/windows/README.md b/documentation/3.4.0/setup/docker/project-with-survey/windows/README.md new file mode 100644 index 00000000..5bf0a10d --- /dev/null +++ b/documentation/3.4.0/setup/docker/project-with-survey/windows/README.md @@ -0,0 +1,324 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - With Samiksha (Windows) + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Windows users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Linux](https://docs.docker.com/desktop/setup/install/windows-install/). To install and use Nodejs in Window machine, you can follow instructions here: [How To Install Nodejs in Linux](https://nodejs.org/en/download/package-manager). + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for %p in (3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569 4301) do @( + netstat -ano | findstr /R /C:":%p " /C:":%p$" >nul + if errorlevel 1 ( + echo Port %p is available + ) else ( + echo Port %p is IN USE + ) +) +``` + +1. **Download Docker Compose File:** Retrieve the **[docker-compose-project.yml](https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml)** file from the Project service repository and save it to the project directory. + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/project-with-survey/docker-compose-project.yml + ``` + + > Note: All commands are run from the project directory. + +2. **Download Environment Files**: Using the OS specific commands given below, download environment files for all the services. + + ``` + curl -L ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/samiksha_env + ``` + +> **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + +> **Caution:** While the default values in the downloaded environment files enable the Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + +3. **Download `docker-compose-up` & `docker-compose-down` Script Files** + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-up.bat + ``` + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/docker-compose-down.bat + ``` + +4. **Download `Config` File** + + ``` + curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json + ``` + + +5. **Run All Services & Dependencies**:All services and dependencies can be started using the `docker-compose-up` script file. + + ``` + docker-compose-up.bat + ``` + +> Double-click the file or run the above command from the terminal. + +> **Note**: During the first Docker Compose run, the database, migration seeder files, and the script to set the default organization will be executed automatically. + +6. **Remove All Service & Dependency Containers**: + All docker containers can be stopped and removed by using the `docker-compose-down` file. + + ``` + docker-compose-down.bat + ``` + +> **Caution**: As per the default configuration in the `docker-compose-project.yml` file, using the `down` command will lead to data loss since the database container does not persist data. To persist data across `down` commands and subsequent container removals, refer to the "Persistence of Database Data in Docker Containers" section of this documentation. + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql + ``` +2. Set up the citus_setup file by following the steps given below. + + 1. Download the `citus_setup.bat` file. + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/windows/citus_setup.bat + ``` + 2. Enable Citus and set distribution columns for `user` database by running the `citus_setup.bat`with the following arguments. + ``` + citus_setup.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + > **Note:** Since the `citus_setup.bat` file requires arguments, it must be run from a terminal. + +## Update Cloud Credentials for Project Service + +To enable full functionalityโ€”including certificate generation, attachment uploads, and report storageโ€”you must configure cloud credentials in the environment files for both services. + +A. Project Service Configuration Path: + ```./project_env + ``` + +B. Samiksha (Survey & Observation) Service Configuration Path: + ```./samiksha_env + ``` + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + 1. **Download The `sampleData.sql` Files:** + + ``` + mkdir sample-data\user 2>nul & ^ + curl -L "https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/project-with-survey/windows/sampleData.sql" -o sample-data\user\sampleData.sql + ``` + +2. **Download The `insert_sample_data` Script File:** + + ``` + curl -L -o insert_sample_data.bat https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/windows/sampleData.sql + ``` + +3. **Run The `insert_sample_data` Script File:** + + ``` + insert_sample_data.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + + After successfully running the script mentioned above, the following user accounts will be created and available for login: + + | Email ID | Password | Role | + | ---------------------- | ---------- | ----------------------- | + | mallanagouda@gmail.com | Password1@ | State Education Officer | + | prajwal@gmail.com | Password1@ | State Education Officer | + | vishnu@gmail.com | Password1@ | State Education Officer | + + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + 1. Download `insert_project_data.bat` Script File: + + ``` + curl -L ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_project_data.bat + ``` + + 2. Make the setup file executable by running the following command. + + ``` + insert_project_data.bat + ``` + 3. Insert Sample Data To Database. + + ``` + node insert_sample_solutions.js + ``` + + + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection +- + Samiksha Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/docker/stand-alone/mac-os/README.md b/documentation/3.4.0/setup/docker/stand-alone/mac-os/README.md new file mode 100644 index 00000000..3dd852fd --- /dev/null +++ b/documentation/3.4.0/setup/docker/stand-alone/mac-os/README.md @@ -0,0 +1,252 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - Stand Alone (Mac-Os) + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Mac users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Mac](https://docs.docker.com/desktop/setup/install/mac-install/). To install and use Nodejs in Mac machine, you can follow instructions here: [How To Install Nodejs in Mac](https://nodejs.org/en/download/package-manager). + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for port in 3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569; do + if sudo lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then + echo "Port $port is IN USE" + else + echo "Port $port is available" + fi +done +``` + +1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/mac-os/setup_project.sh \ + && chmod +x setup_project.sh \ + && ./setup_project.sh + ``` + +> Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. + +**General Instructions :** + +1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. +2. All docker containers can be stopped and removed by using below command. + +``` +sudo ./docker-compose-down.sh +``` + +3. All services and dependencies can be started using below command. + +``` +sudo ./docker-compose-up.sh +``` + +**Keep the current terminal session active, and kindly open a new terminal window within the project directory.** + +**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. + + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` + +2. Set up the citus_setup file by following the steps given below. + + 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + + ``` + sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + +## Update Cloud Credentials for Project Service + +To enable full functionality, including certificate generation and report storage, you must configure cloud credentials in the Project Service environment file. + + Path: ./project_env + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available [here](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +docker exec -i citus_master psql -U postgres -d user < insert_sample_data.sql +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + ``` + node insert_sample_solutions.js + ``` + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- +# Team + + + + + +--- +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/docker/stand-alone/ubuntu/README.md b/documentation/3.4.0/setup/docker/stand-alone/ubuntu/README.md new file mode 100644 index 00000000..52dfca8a --- /dev/null +++ b/documentation/3.4.0/setup/docker/stand-alone/ubuntu/README.md @@ -0,0 +1,252 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - Stand Alone (Ubuntu) + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Linux users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Linux](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04). To install and use Nodejs in Linux machine, you can follow instructions here: [How To Install Nodejs in Linux](https://nodejs.org/en/download/package-manager). + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for port in 3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569; do + if sudo lsof -iTCP:$port -sTCP:LISTEN &>/dev/null; then + echo "Port $port is IN USE" + else + echo "Port $port is available" + fi +done +``` + +1. **Download and execute main setup script:** Execute the following command in your terminal from the project directory. + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/ubuntu/setup_project.sh && chmod +x setup_project.sh && sudo ./setup_project.sh + ``` + +> Note : The script will download all the essential files and launch the services in Docker. Once all services are successfully up and running, you can proceed to the next steps. + +**General Instructions :** + +1. All containers which are part of the docker-compose can be gracefully stopped by pressing Ctrl + c in the same terminal where the services are running. +2. All docker containers can be stopped and removed by using below command. + +``` +sudo ./docker-compose-down.sh +``` + +3. All services and dependencies can be started using below command. + +``` +sudo ./docker-compose-up.sh +``` + +**Keep the current terminal session active, and kindly open a new terminal window within the project directory.** + +**After successfully completing this, please move to the next section: [Enable Citus Extension](#enable-citus-extension-optional)** + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. (Skip this for linux) + + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/distribution-columns/user/distributionColumns.sql + ``` + +2. Set up the citus_setup file by following the steps given below. + + 1. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + + ``` + sudo ./citus_setup.sh user postgres://postgres:postgres@citus_master:5432/user + ``` + +## Update Cloud Credentials for Project Service + +To enable full functionality, including certificate generation and report storage, you must configure cloud credentials in the Project Service environment file. + + Path: ./project_env + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +sudo chmod +x ./insert_sample_data.sh && sudo ./insert_sample_data.sh user postgres://postgres:postgres@citus_master:5432/user +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + ``` + node insert_sample_solutions.js + ``` + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- + +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/docker/stand-alone/windows/README.md b/documentation/3.4.0/setup/docker/stand-alone/windows/README.md new file mode 100644 index 00000000..4e3d7b3c --- /dev/null +++ b/documentation/3.4.0/setup/docker/stand-alone/windows/README.md @@ -0,0 +1,318 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Docker Setup Project Service - Stand Alone (Windows) + +Expectation: By diligently following the outlined steps, you will successfully establish a fully operational Project application setup, including both the portal and backend services. + +## Prerequisites + +To set up the Project application, ensure you have Docker and Docker Compose installed on your system. For Windows users, detailed installation instructions for both can be found in the documentation here: [How To Install and Use Docker Compose on Linux](https://docs.docker.com/desktop/setup/install/windows-install/). To install and use Nodejs in Window machine, you can follow instructions here: [How To Install Nodejs in Linux](https://nodejs.org/en/download/package-manager). + + +## Installation + +**Create project Directory:** Establish a directory titled **project**. + +> Example Command: `mkdir project && cd project/` + +> Note: All commands are run from the project directory. + +## Checking Port Availability + +> **Caution:** Before proceeding, please ensure that the ports given here are available and open. It is essential to verify their availability prior to moving forward. You can run below command in your terminal to check this + +``` +for %p in (3001 3002 6000 5001 4000 9092 5432 7007 2181 27017 3569) do @( + netstat -ano | findstr /R /C:":%p " /C:":%p$" >nul + if errorlevel 1 ( + echo Port %p is available + ) else ( + echo Port %p is IN USE + ) +) +``` + +1. **Download Docker Compose File:** Retrieve the **[docker-compose-project.yml](https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/docker-compose-project.yml)** file from the Project service repository and save it to the project directory. + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/dockerFiles/stand-alone/docker-compose-project.yml + ``` + + > Note: All commands are run from the project directory. + +2. **Download Environment Files**: Using the OS specific commands given below, download environment files for all the services. + + ``` + curl -L ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/interface_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/entity_management_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/project_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/notification_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/scheduler_env ^ + -O https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/envs/user_env + ``` + +> **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + +> **Caution:** While the default values in the downloaded environment files enable the Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + +3. **Download `docker-compose-up` & `docker-compose-down` Script Files** + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-up.bat + ``` + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/dockerized/scripts/stand-alone/windows/docker-compose-down.bat + ``` + +4. **Download `Config` File** + + ``` + curl -L https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json -o config.json + ``` + + +5. **Run All Services & Dependencies**:All services and dependencies can be started using the `docker-compose-up` script file. + + ``` + docker-compose-up.bat + ``` + +> Double-click the file or run the above command from the terminal. + +> **Note**: During the first Docker Compose run, the database, migration seeder files, and the script to set the default organization will be executed automatically. + +6. **Remove All Service & Dependency Containers**: + All docker containers can be stopped and removed by using the `docker-compose-down` file. + + ``` + docker-compose-down.bat + ``` + +> **Caution**: As per the default configuration in the `docker-compose-project.yml` file, using the `down` command will lead to data loss since the database container does not persist data. To persist data across `down` commands and subsequent container removals, refer to the "Persistence of Database Data in Docker Containers" section of this documentation. + +## Enable Citus Extension (Optional) + +User management service comes with this bundle relies on PostgreSQL as its core database system. To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + +For more information, refer **[Citus Data](https://www.citusdata.com/)**. + +To enable the Citus extension for user services, follow these steps. + +1. Create a sub-directory named `user` and download `distributionColumns.sql` into it. + ``` + mkdir user && curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql + ``` +2. Set up the citus_setup file by following the steps given below. + + 1. Download the `citus_setup.bat` file. + ``` + curl -OJL https://github.com/ELEVATE-Project/project-service/raw/main/documentation/1.0.0/dockerized/scripts/windows/citus_setup.bat + ``` + 2. Enable Citus and set distribution columns for `user` database by running the `citus_setup.bat`with the following arguments. + ``` + citus_setup.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + > **Note:** Since the `citus_setup.bat` file requires arguments, it must be run from a terminal. + + +## Update Cloud Credentials for Project Service + +To enable full functionality, including certificate generation and report storage, you must configure cloud credentials in the Project Service environment file. + + Path: ./project_env + +Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + +> NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + +For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +## Persistence Of Database Data In Docker Container (Optional) + +To ensure the persistence of database data when running `docker compose down`, it is necessary to modify the `docker-compose-project.yml` file according to the steps given below: + +1. **Modification Of The `docker-compose-project.yml` File:** + + Begin by opening the `docker-compose-project.yml` file. Locate the section pertaining to the Citus and mongo container and proceed to uncomment the volume specification. This action is demonstrated in the snippet provided below: + + ```yaml + mongo: + image: 'mongo:4.4.14' + restart: 'always' + ports: + - '27017:27017' + networks: + - project_net + volumes: + - mongo-data:/data/db + logging: + driver: none + + citus: + image: citusdata/citus:11.2.0 + container_name: 'citus_master' + ports: + - 5432:5432 + volumes: + - citus-data:/var/lib/postgresql/data + ``` + +2. **Uncommenting Volume Names Under The Volumes Section:** + + Next, navigate to the volumes section of the file and proceed to uncomment the volume names as illustrated in the subsequent snippet: + + ```yaml + networks: + elevate_net: + external: false + + volumes: + citus-data: + mongo-data: + ``` + +By implementing these adjustments, the configuration ensures that when the `docker-compose down` command is executed, the database data is securely stored within the specified volumes. Consequently, this data will be retained and remain accessible, even after the containers are terminated and subsequently reinstated using the `docker-compose up` command. + +## Sample User Accounts Generation + +During the initial setup of Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + 1. **Download The `sampleData.sql` Files:** + + ``` + mkdir sample-data\user 2>nul & ^ + curl -L "https://raw.githubusercontent.com/MallanagoudaBiradar/project-service/refs/heads/windowsStandAlone/documentation/3.4.0/dockerized/scripts/stand-alone/windows/sampleData.sql" -o sample-data\user\sampleData.sql + ``` + +2. **Download The `insert_sample_data` Script File:** + + ``` + curl -L -o insert_sample_data.bat https://raw.githubusercontent.com/MallanagoudaBiradar/project-service/refs/heads/windowsStandAlone/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_sample_data.bat + ``` + +3. **Run The `insert_sample_data` Script File:** + + ``` + insert_sample_data.bat user postgres://postgres:postgres@citus_master:5432/user + ``` + + After successfully running the script mentioned above, the following user accounts will be created and available for login: + + | Email ID | Password | Role | + | ---------------------- | ---------- | ----------------------- | + | mallanagouda@gmail.com | Password1@ | State Education Officer | + | prajwal@gmail.com | Password1@ | State Education Officer | + | vishnu@gmail.com | Password1@ | State Education Officer | + + +## Sample Data Creation For Projects + +This step will guide us in implementing a sample project solution following the initial setup of the project service. + +1. **Insert Sample Data To Database:** + + 1. Download `insert_project_data.bat` Script File: + + ``` + curl -L ^ + -O https://raw.githubusercontent.com/MallanagoudaBiradar/project-service/refs/heads/windowsStandAlone/documentation/3.4.0/dockerized/scripts/stand-alone/windows/insert_project_data.bat + ``` + + 2. Make the setup file executable by running the following command. + + ``` + insert_project_data.bat + ``` + 3. Insert Sample Data To Database. + + ``` + node insert_sample_solutions.js + ``` + + + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +> **Warning:** In this setup, features such as **Sign-Up, Project Certificate, Project Sharing, and Project PDF Report** will not be available because cloud storage credentials have been masked in the environment files for security reasons. + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/native/project-with-survey/ubuntu/README.md b/documentation/3.4.0/setup/native/project-with-survey/ubuntu/README.md new file mode 100644 index 00000000..b288d635 --- /dev/null +++ b/documentation/3.4.0/setup/native/project-with-survey/ubuntu/README.md @@ -0,0 +1,321 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Native Setup Project Service - With Survey (Ubuntu) + +This section describes the native setup, where all required dependencies and services are installed and managed directly on the host system using PM2, without Docker. This setup is primarily intended for local development and debugging. + +### System Requirements + +- **Node.jsยฎ:** v20 +- **PostgreSQL:** 16 +- **Apache Kafkaยฎ:** 3.5.0 +- **MongoDB:** 4.4.14 +- **Gotenberg:** 8.5.0 + +Expectation: By following these steps, you will establish a unified environment for the Project Service, integrated with the Survey and Observation modules. This setup focuses purely on the backend API infrastructure required to manage data collection and reporting. + +Before setting up the following ELEVATE-Project application, dependencies given below should be installed and verified to be running. Refer to the steps given below to install them and verify. + +1. Download dependency management scripts: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/check-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/install-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/uninstall-dependencies.sh && \ + chmod +x check-dependencies.sh && \ + chmod +x install-dependencies.sh && \ + chmod +x uninstall-dependencies.sh + ``` + +2. Verify installed dependencies by running `check-dependencies.sh`: + + ``` + ./check-dependencies.sh + ``` + + > Note: Keep note of any missing dependencies. + +3. Install dependencies by running `install-dependencies.sh`: + ``` + ./install-dependencies.sh + ``` + > Note: Install all missing dependencies and use check-dependencies script to ensure everything is installed and running. +4. Uninstall dependencies by running `uninstall-dependencies.sh`: + + ``` + ./uninstall-dependencies.sh + ``` + + > Warning: Due to the destructive nature of the script (without further warnings), it should only be used during the initial setup of the dependencies. For example, Uninstalling PostgreSQL/Citus using script will lead to data loss. USE EXTREME CAUTION. + + > Warning: This script should only be used to uninstall dependencies that were installed via installation script in step 3. If same dependencies were installed using other methods, refrain from using this script. This script is provided in-order to reverse installation in-case issues arise from a bad install. + +## Installation + +1. **Create ELEVATE-Project Directory:** Create a directory named **ELEVATE-Project**. + + > Example Command: `mkdir ELEVATE-Project && cd ELEVATE-Project/` + +2. **Git Clone Services And Portal Repositories** + +``` +git clone -b develop https://github.com/ELEVATE-Project/project-service.git && \ +git clone -b develop https://github.com/ELEVATE-Project/entity-management.git && \ +git clone -b develop https://github.com/ELEVATE-Project/user.git && \ +git clone -b main https://github.com/ELEVATE-Project/interface-service.git && \ +git clone -b develop https://github.com/ELEVATE-Project/samiksha-service && \ +git clone -b master https://github.com/ELEVATE-Project/scheduler.git +``` + +3. **Install NPM Packages** + +``` +cd project-service && npm install && cd ../ && \ +cd samiksha-service && npm install && cd ../ && \ +cd entity-management/src && npm install && cd ../.. && \ +cd user/src && npm install && cd ../.. && \ +cd interface-service/src && npm install && cd ../.. && \ +cd scheduler/src && npm install && cd ../.. +``` + +4. **Download Environment Files** + +``` +curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/project_env && \ +curl -L -o samiksha-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/samiksha_env && \ +curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/entity_management_env && \ +curl -L -o user/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/user_env && \ +curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/interface_env && \ +curl -L -o scheduler/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/project-with-survey/scheduler_env +``` + +> **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-Management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + +> **Caution:** While the default values in the downloaded environment files enable the ELEVATE-Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + +> **Important:** As mentioned in the above linked document, the **User SignUp** functionality may be compromised if key environment variables are not set correctly during deployment. If you opt to skip this setup, consider using the sample user account generator detailed in the `Sample User Accounts Generation` section of this document. + +5. **Attaching Config File** + + ``` + curl -L -o project-service/config.json https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json && \ + curl -L -o samiksha-service/config.json https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json && \ + curl -L -o entity-management/src/config.json https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json + ``` + +6. **Create Databases** + + 1. Download `create-databases.sh` Script File: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/create-databases.sh + ``` + + 2. Make the executable by running the following command: + + ``` + chmod +x create-databases.sh + ``` + + 3. Run the script file: + + ``` + ./create-databases.sh + ``` + +7. **Run Migrations and Seed To Create Tables** + + 1. run migrations + + ``` + cd user/src && npx sequelize-cli db:migrate && cd ../.. + ``` + + 2. run Seed + ``` + cd user/src && npx sequelize-cli db:seed:all && cd ../../ + ``` + +8. **Enabling Citus And Setting Distribution Columns (Optional)** + + To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + + > NOTE: Currently only available for Linux based operation systems. + + 1. Download user `distributionColumns.sql` file. + + ``` + curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql + ``` + + 2. Set up the `citus_setup` file by following the steps given below. + + 1. Download the `citus_setup.sh` file: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/citus_setup.sh + ``` + + 2. Make the setup file executable by running the following command: + + ``` + chmod +x citus_setup.sh + ``` + + 3. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + ``` + ./citus_setup.sh user postgres://postgres:postgres@localhost:9700/users + ``` + +9. **Update Cloud Credentials for Project Service** + + To enable full functionalityโ€”including certificate generation, attachment uploads, and report storageโ€”you must configure cloud credentials in the environment files for both services. + + A. Project Service Configuration Path: + ```./ELEVATE-Project/project-service/.env + ``` + + B. Samiksha (Survey & Observation) Service Configuration Path: + ```./ELEVATE-Project/samiksha-service/.env + ``` + + + + Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + + > NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + + For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +11. **Insert Initial Data** + + 1. Download `entity-project-sample-data.sh` Script File: + + ``` + curl -o project_entity_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/project_entity_sample_data.sh && \ + chmod +x project_entity_sample_data.sh && \ + ./project_entity_sample_data.sh + ``` + +12. **Start The Services** + + Following the steps given below, 2 instances of each ELEVATE-Project backend service will be deployed and be managed by PM2 process manager. + + ``` + (cd project-service && pm2 start app.js --name project-service && cd -) && \ + (cd samiksha-service && pm2 start app.js --name samiksha-service && cd -) && \ + (cd entity-management/src && pm2 start app.js --name entity-management && cd -) && \ + (cd user/src && pm2 start app.js --name user && cd -) && \ + (cd interface-service/src && pm2 start app.js --name interface && cd -) && \ + (cd scheduler/src && pm2 start app.js --name scheduler && cd -) + ``` + + +## Sample User Accounts Generation + +During the initial setup of ELEVATE-Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the ELEVATE-Project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the ELEVATE-Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/project-with-survey/ubuntu/insert_sample_data.sh && \ +chmod +x insert_sample_data.sh && \ +./insert_sample_data.sh +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +--- + + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) +- **Observtaion/Survey Portal:** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-portal/tree/release-3.4.0) + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection +- + Samiksha Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- + +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/documentation/3.4.0/setup/native/stand-alone/ubuntu/README.md b/documentation/3.4.0/setup/native/stand-alone/ubuntu/README.md new file mode 100644 index 00000000..3de8666f --- /dev/null +++ b/documentation/3.4.0/setup/native/stand-alone/ubuntu/README.md @@ -0,0 +1,308 @@ +
+ +# Projects Service + + + + + +![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/ELEVATE-Project/mentoring?filename=src%2Fpackage.json) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + + + + +
+The Project building block facilitates the creation and engagement with micro-improvement projects. + +
+
+ +# Native Setup Project Service - Stand Alone (Ubuntu) + +This section describes the native setup, where all required dependencies and services are installed and managed directly on the host system using PM2, without Docker. This setup is primarily intended for local development and debugging. + +### System Requirements + +- **Node.jsยฎ:** v20 +- **PostgreSQL:** 16 +- **Apache Kafkaยฎ:** 3.5.0 +- **MongoDB:** 4.4.14 +- **Gotenberg:** 8.5.0 + +Expectation: Upon following the prescribed steps, you will achieve a fully operational ELEVATE-Project application setup. Both the portal and backend services are managed using PM2, with all dependencies installed natively on the host system. + +## Prerequisites + +Before setting up the following ELEVATE-Project application, dependencies given below should be installed and verified to be running. Refer to the steps given below to install them and verify. + +1. Download dependency management scripts: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/check-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/install-dependencies.sh && \ + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/uninstall-dependencies.sh && \ + chmod +x check-dependencies.sh && \ + chmod +x install-dependencies.sh && \ + chmod +x uninstall-dependencies.sh + ``` + +2. Verify installed dependencies by running `check-dependencies.sh`: + + ``` + ./check-dependencies.sh + ``` + + > Note: Keep note of any missing dependencies. + +3. Install dependencies by running `install-dependencies.sh`: + ``` + ./install-dependencies.sh + ``` + > Note: Install all missing dependencies and use check-dependencies script to ensure everything is installed and running. +4. Uninstall dependencies by running `uninstall-dependencies.sh`: + + ``` + ./uninstall-dependencies.sh + ``` + + > Warning: Due to the destructive nature of the script (without further warnings), it should only be used during the initial setup of the dependencies. For example, Uninstalling PostgreSQL/Citus using script will lead to data loss. USE EXTREME CAUTION. + + > Warning: This script should only be used to uninstall dependencies that were installed via installation script in step 3. If same dependencies were installed using other methods, refrain from using this script. This script is provided in-order to reverse installation in-case issues arise from a bad install. + +## Installation + +1. **Create ELEVATE-Project Directory:** Create a directory named **ELEVATE-Project**. + + > Example Command: `mkdir ELEVATE-Project && cd ELEVATE-Project/` + +2. **Git Clone Services And Portal Repositories** + +``` +git clone -b develop https://github.com/ELEVATE-Project/project-service.git && \ +git clone -b develop https://github.com/ELEVATE-Project/entity-management.git && \ +git clone -b develop https://github.com/ELEVATE-Project/user.git && \ +git clone -b main https://github.com/ELEVATE-Project/interface-service.git && \ +git clone -b master https://github.com/ELEVATE-Project/scheduler.git +``` + +3. **Install NPM Packages** + +``` +cd project-service && npm install && cd ../ && \ +cd entity-management/src && npm install && cd ../.. && \ +cd user/src && npm install && cd ../.. && \ +cd interface-service/src && npm install && cd ../.. && \ +cd scheduler/src && npm install && cd ../.. +``` + +4. **Download Environment Files** + +``` +curl -L -o project-service/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/stand-alone/project_env && \ +curl -L -o entity-management/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/stand-alone/entity_management_env && \ +curl -L -o user/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/stand-alone/user_env && \ +curl -L -o interface-service/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/stand-alone/interface_env && \ +curl -L -o scheduler/src/.env https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/envs/stand-alone/scheduler_env +``` + +> **Note:** Modify the environment files as necessary for your deployment using any text editor, ensuring that the values are appropriate for your environment. The default values provided in the current files are functional and serve as a good starting point. Refer to the sample env files provided at the [Project](https://github.com/ELEVATE-Project/project-service/blob/main/.env.sample), [User](https://github.com/ELEVATE-Project/user/blob/master/src/.env.sample), [Notification](https://github.com/ELEVATE-Project/notification/blob/master/src/.env.sample), [Scheduler](https://github.com/ELEVATE-Project/scheduler/blob/master/src/.env.sample), [Interface](https://github.com/ELEVATE-Project/interface-service/blob/main/src/.env.sample) and [Entity-Management](https://github.com/ELEVATE-Project/entity-management/blob/main/src/.env.sample) repositories for reference. + +> **Caution:** While the default values in the downloaded environment files enable the ELEVATE-Project Application to operate, certain features may not function correctly or could be impaired unless the adopter-specific environment variables are properly configured. + +> **Important:** As mentioned in the above linked document, the **User SignUp** functionality may be compromised if key environment variables are not set correctly during deployment. If you opt to skip this setup, consider using the sample user account generator detailed in the `Sample User Accounts Generation` section of this document. + +5. **Attaching Config File** + + ``` + curl -L -o project-service/config.json https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json && \ + curl -L -o entity-management/src/config.json https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/common-files/generics/configFile.json + ``` + +6. **Create Databases** + + 1. Download `create-databases.sh` Script File: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/create-databases.sh + ``` + + 2. Make the executable by running the following command: + + ``` + chmod +x create-databases.sh + ``` + + 3. Run the script file: + + ``` + ./create-databases.sh + ``` + +7. **Run Migrations and Seed To Create Tables** + + 1. run migrations + + ``` + cd user/src && npx sequelize-cli db:migrate && cd ../.. + ``` + + 2. run Seed + ``` + cd user/src && npx sequelize-cli db:seed:all && cd ../../ + ``` + +8. **Enabling Citus And Setting Distribution Columns (Optional)** + + To boost performance and scalability, users can opt to enable the Citus extension. This transforms PostgreSQL into a distributed database, spreading data across multiple nodes to handle large datasets more efficiently as demand grows. + + > NOTE: Currently only available for Linux based operation systems. + + 1. Download user `distributionColumns.sql` file. + + ``` + curl -o ./user/distributionColumns.sql -JL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/distribution-columns/user/distributionColumns.sql + ``` + + 2. Set up the `citus_setup` file by following the steps given below. + + 1. Download the `citus_setup.sh` file: + + ``` + curl -OJL https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/1.0.0/native/scripts/linux/citus_setup.sh + ``` + + 2. Make the setup file executable by running the following command: + + ``` + chmod +x citus_setup.sh + ``` + + 3. Enable Citus and set distribution columns for `user` database by running the `citus_setup.sh`with the following arguments. + ``` + ./citus_setup.sh user postgres://postgres:postgres@localhost:9700/users + ``` + +9. **Update Cloud Credentials for Project Service** + + To enable full functionality, including certificate generation and report storage, you must configure cloud credentials in the Project Service environment file. + + Path: ./ELEVATE-Project/project-service/.env + + Add or update the following variables in the .env file, substituting the example values with your actual cloud credentials: + + CLOUD_STORAGE_PROVIDER=gcloud + CLOUD_STORAGE_ACCOUNTNAME=your_account_name + CLOUD_STORAGE_SECRET="-----BEGIN PRIVATE KEY-----\n..." + CLOUD_STORAGE_PROJECT=your_cloud_project_id + CLOUD_STORAGE_BUCKETNAME=your_bucket_name + CLOUD_STORAGE_BUCKET_TYPE=private + + > NOTE : This service is designed to support multiple cloud storage providers and offers flexible cloud integration capabilities. Based on your selected cloud provider, the service can be configured accordingly to enable seamless storage, certificate generation, and report handling. + + For detailed configuration options, supported cloud providers, and integration guidelines, please refer to the official documentation available in this [ReadMe](https://www.npmjs.com/package/client-cloud-services?activeTab=readme) + +10. **Insert Initial Data** + + 1. Download `entity-project-sample-data.sh` Script File: + + ``` + curl -o project_entity_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/project_entity_sample_data.sh && \ + chmod +x project_entity_sample_data.sh && \ + ./project_entity_sample_data.sh + ``` + +11. **Start The Services** + + Following the steps given below, 2 instances of each ELEVATE-Project backend service will be deployed and be managed by PM2 process manager. + + ``` + (cd project-service && pm2 start app.js --name project-service && cd -) && \ + (cd entity-management/src && pm2 start app.js --name entity-management && cd -) && \ + (cd user/src && pm2 start app.js --name user && cd -) && \ + (cd interface-service/src && pm2 start app.js --name interface && cd -) && \ + (cd scheduler/src && pm2 start app.js --name scheduler && cd -) + ``` + +## Sample User Accounts Generation + +During the initial setup of ELEVATE-Project services with the default configuration, you may encounter issues creating new accounts through the regular SignUp flow on the ELEVATE-Project portal. This typically occurs because the default SignUp process includes OTP verification to prevent abuse. Until the notification service is configured correctly to send actual emails, you will not be able to create new accounts. + +In such cases, you can generate sample user accounts using the steps below. This allows you to explore the ELEVATE-Project services and portal immediately after setup. + +> **Warning:** Use this generator only immediately after the initial system setup and before any normal user accounts are created through the portal. It should not be used under any circumstances thereafter. + +``` +curl -o insert_sample_data.sh https://raw.githubusercontent.com/ELEVATE-Project/project-service/refs/heads/main/documentation/3.4.0/native/scripts/stand-alone/ubuntu/insert_sample_data.sh && \ +chmod +x insert_sample_data.sh && \ +./insert_sample_data.sh +``` + +After successfully running the script mentioned above, the following user accounts will be created and available for login: + +| Email ID | Password | Role | +| ---------------------- | ---------- | ----------------------- | +| mallanagouda@gmail.com | Password1@ | State Education Officer | +| prajwal@gmail.com | Password1@ | State Education Officer | +| vishnu@gmail.com | Password1@ | State Education Officer | + +--- + + +## ๐ŸŒ Micro-Frontend (FE) Setup + +The ELEVATE application uses a micro-frontend architecture. After setting up the backend services, you must configure and run the frontend repositories to access the application via the portal. + +Follow the setup guides for the frontend repositories: + +- **Login Portal:** [elevate-portal](https://github.com/ELEVATE-Project/elevate-portal/tree/releaase-1.1.0) +- **Projects Program Module (PWA):** [observation-survey-projects-pwa](https://github.com/ELEVATE-Project/observation-survey-projects-pwa/tree/release-3.4.0) + +--- + +### ๐Ÿงช Postman Collections and API DOC + +- + Projects Service API Collection + + +--- + +### ๐Ÿ› ๏ธ Adding New Projects to the System + +With SUP (Solution Upload Portal), you can seamlessly add new projects , survey and observation to the system. +Once it's successfully added, it becomes visible on the portal, ready for use and interaction. + +For a comprehensive guide on setting up and using the SUP, please refer to: + +- + solution-Upload-Portal-Service +- + solution-Upload-Portal + + +--- + +# Team + + + + + +--- + +# Open Source Dependencies + +This project uses several open-source tools and dependencies that supported its development + +![NodeJS](https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white) +![Apache Kafka](https://img.shields.io/badge/Apache%20Kafka-000?style=for-the-badge&logo=apachekafka) +![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) +![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) +![MongoDB](https://img.shields.io/badge/MongoDB-4EA94B?style=for-the-badge&logo=mongodb&logoColor=white) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) +![RabbitMQ](https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white) diff --git a/generics/services/survey.js b/generics/services/survey.js index 8d055dde..555d6d67 100644 --- a/generics/services/survey.js +++ b/generics/services/survey.js @@ -333,10 +333,10 @@ const createObservation = function (token, solutionId, data, userRoleAndProfileI * @param {String} resourceType - Type of the resource being deleted ('solution', 'program', etc.). * @param {String} tenantId - Tenant identifier (used for multi-tenancy). * @param {String} orgId - Organization ID from where the deletion is triggered. - * + * @param {String} isAPrivateProgram - If Program is Private `true` else `false`. * @returns {Promise} - Result indicating success/failure and optional response data. */ -const deleteSolutionResource = function (solutionIds, resourceType, tenantId, orgId, userId) { +const deleteSolutionResource = function (solutionIds, resourceType, tenantId, orgId, userId, isAPrivateProgram) { return new Promise(async (resolve, reject) => { try { // Construct the API URL to call the delete endpoint on the Survey Service @@ -353,6 +353,7 @@ const deleteSolutionResource = function (solutionIds, resourceType, tenantId, or tenantId: tenantId, orgId: orgId, deletedBy: userId, + isAPrivateProgram: isAPrivateProgram, }, } // Send a POST request to the Survey Service to delete the resource diff --git a/migrations/tenantMigration/MAIN-README.md b/migrations/tenantMigration/MAIN-README.md new file mode 100644 index 00000000..479ed450 --- /dev/null +++ b/migrations/tenantMigration/MAIN-README.md @@ -0,0 +1,98 @@ +# ๐Ÿ› ๏ธ Tenant Migration Execution Guide + +## ๐Ÿ“Œ Overview + +This document provides the **correct order and references** to execute tenant migration scripts across services. + +Follow the sequence strictly to ensure: + +- Data consistency +- Proper reference mapping +- Successful downstream migrations + +--- + +## ๐Ÿš€ Execution Order + +### 1๏ธโƒฃ Entity Service + +- Must be executed **first** +- Handles all base entity data (state, district, school, etc.) +- Other services depend on entity mappings + +๐Ÿ”— README: +https://github.com/ELEVATE-Project/entity-management/blob/develop/src/migrations/tenantMigration/readMe.md + +--- + +### 2๏ธโƒฃ User Service + +- Execute after entity migration +- Migrates user-related data and profiles + +๐Ÿ”— README: +https://github.com/ELEVATE-Project/user/blob/develop/src/scripts/readme.md + +--- + +### 3๏ธโƒฃ Project Service + +- Depends on both entity & user data +- Migrates: + + - Programs + - Solutions + - Projects + - Templates + +๐Ÿ”— README: +https://github.com/ELEVATE-Project/project-service/blob/develop/migrations/tenantMigration/README.md + +--- + +### 4๏ธโƒฃ Survey Service (Samiksha) + +- Should be executed **last** +- Depends on project and user mappings + +๐Ÿ”— README: +https://github.com/ELEVATE-Project/samiksha-service/blob/develop/migrations/tenantMigration/README.md + +--- + +## โš ๏ธ Important Notes + +- Follow the order strictly: + **Entity โ†’ User โ†’ Project โ†’ Survey** + +- Ensure: + + - Same tenant IDs are used across all services + - Migration reference IDs are preserved + - Required environment variables are set + +- Always: + + - Run in **staging first** + - Validate data after each step + +--- + +## โœ… Summary + +| Step | Service | Dependency | +| ---- | ------- | ------------- | +| 1 | Entity | None | +| 2 | User | Entity | +| 3 | Project | Entity, User | +| 4 | Survey | Project, User | + +--- + +## ๐Ÿ Final Note + +Run each service migration **independently and verify before proceeding** to the next. + +--- + +## Caution : Please check with Data team if they have to any process before executing the above scripts. diff --git a/migrations/tenantMigration/README.md b/migrations/tenantMigration/README.md new file mode 100644 index 00000000..17768603 --- /dev/null +++ b/migrations/tenantMigration/README.md @@ -0,0 +1,226 @@ +# ๐Ÿ› ๏ธ Tenant Migration Script + +## ๐Ÿ“Œ Overview + +This script is used to **migrate data between tenants and organizations** in MongoDB. +It handles multiple collections, updates references, and ensures consistency across related data. + +Additionally, it: + +- Validates user access via JWT (admin-only) +- Updates entity references via external service +- Pushes migrated project data to Kafka +- Generates a migration output report + +--- + +## โš™๏ธ Prerequisites + +- Node.js (v16+ recommended) +- MongoDB access +- `.env` file configured +- Input configuration file (`input.json`) + +--- + +## ๐Ÿ“ Environment Variables + +Create a `.env` file in the root directory: + +```env +MONGODB_URL= +ACCESS_TOKEN_SECRET= +INTERFACE_SERVICE_URL= +ENTITY_MANAGEMENT_SERVICE_BASE_URL= +USER_SERVICE_BASE_URL= +INTERNAL_ACCESS_TOKEN= +``` + +--- + +## ๐Ÿ“ฅ Input File + +Provide an `input.json` file in the same directory: + +```json +{ + "currentTenantId": "oldTenant", + "currentOrgId": "oldOrg", + "newTenantId": "newTenant", + "newOrgId": "newOrg", + "token": "your-jwt-token" +} +``` + +--- + +## ๐Ÿ” Token Validation + +- The script verifies the JWT token using `ACCESS_TOKEN_SECRET` +- It ensures the user has an **admin role** +- If not, the script exits with: + + ``` + Unauthorized + ``` + +--- + +## ๐Ÿ“ฆ Collections Covered + +The script migrates the following collections: + +- certificateBaseTemplates +- projectCategories +- certificateTemplates +- organizationExtension +- programs +- projectTemplates +- projectTemplateTasks +- projects +- solutions +- userExtension +- userCourses + +--- + +## ๐Ÿš€ How It Works + +### 1. Data Filtering + +Each collection is filtered by: + +- `tenantId` +- `orgId` +- Excludes already migrated documents + +--- + +### 2. Migration Strategy + +#### ๐Ÿ”น Insert-based migration + +- Creates new documents with: + + - New `_id` + - Updated `tenantId` and `orgId` + - `tenantMigrationReferenceId` + +#### ๐Ÿ”น Update-based migration + +- Updates existing documents in-place +- Used for: + + - organizationExtension + - projectTemplateTasks + +--- + +### 3. Reference Mapping + +Handles mapping for: + +- Categories +- Entities (state, district, etc.) +- Base templates +- Programs & solutions + +Uses: + +- `tenantMigrationReferenceId` +- External entity service + +--- + +### 4. User Data Enrichment + +- Fetches user profile via API +- Updates `userProfile` field + +--- + +### 5. Kafka Push + +After migrating `projects`: + +- Each project is pushed to Kafka +- Includes a **1-second delay** between pushes + +--- + +### 6. Batch Processing + +- Uses `BATCH_SIZE = 10` +- Bulk operations via `bulkWrite` +- Adds **3-second delay** between batches + +--- + +## ๐Ÿ“Š Output + +A file is generated: + +``` +output-.json +``` + +### Format: + +```json +{ + "collectionName": { + "count": 100, + "data": [ + { + "_id": "newId", + "migrationReferenceId": "oldId" + } + ] + } +} +``` + +--- + +## โ–ถ๏ธ Run the Script + +```bash +node your-script-file.js +``` + +--- + +## ๐Ÿง  Key Features + +- โœ… Safe migration using batching +- โœ… Reference integrity maintained +- โœ… Admin-only execution +- โœ… External service integration +- โœ… Kafka event triggering +- โœ… Migration audit output + +--- + +## โš ๏ธ Notes + +- Ensure **correct tenant/org IDs** before running +- Run in a **non-production environment first** +- Kafka push depends on valid token +- External services must be reachable + +--- + +## ๐Ÿงน Cleanup & Exit + +- Closes MongoDB connection after execution +- Exits process with status `1` (intentional termination) + +--- + +## โš ๏ธ Disclaimer + +``` +Solutions created for other organizations will not be subjected for migration. +``` + +--- diff --git a/migrations/tenantMigration/input.json b/migrations/tenantMigration/input.json new file mode 100644 index 00000000..52313b30 --- /dev/null +++ b/migrations/tenantMigration/input.json @@ -0,0 +1,7 @@ +{ + "currentTenantId": "", + "currentOrgId": "", + "newTenantId": "", + "newOrgId": "", + "token": "<--token-->" +} diff --git a/migrations/tenantMigration/tenantMigration.js b/migrations/tenantMigration/tenantMigration.js new file mode 100644 index 00000000..a42ec1de --- /dev/null +++ b/migrations/tenantMigration/tenantMigration.js @@ -0,0 +1,1239 @@ +/** + * Tenant Migration Script + * -------------------------- + */ + +const path = require('path') +const rootPath = path.join(__dirname, '../../') +require('dotenv').config({ path: rootPath + '/.env' }) +const { MongoClient, ObjectId } = require('mongodb') +const fs = require('fs') +const http = require('http') +const request = require('request') +const jwt = require('jsonwebtoken') +const MONGO_URL = process.env.MONGODB_URL +const BATCH_SIZE = 100 +const interfaceServiceUrl = process.env.INTERFACE_SERVICE_URL + +// Add collections here +const collections = [ + 'certificateBaseTemplates', + 'projectCategories', + 'certificateTemplates', + 'organizationExtension', + 'programs', + 'solutions', + 'projectTemplates', + 'projectTemplateTasks', + 'projects', + 'userExtension', + 'userCourses', +] + +let kafkaPushSuccessProjects = [] +let kafkaPushFailedProjects = [] + +if (!MONGO_URL) { + console.error('โŒ MONGO_URL missing in .env') + process.exit(1) +} + +const inputFilePath = path.resolve(__dirname, './input.json') +const rawData = fs.readFileSync(inputFilePath, 'utf8') +let inputData = JSON.parse(rawData) +const timeStamp = new Date() + +;['currentTenantId', 'currentOrgId', 'newTenantId', 'newOrgId'].forEach((key) => { + if (inputData[key]) { + inputData[key] = inputData[key].toLowerCase() + } +}) + +const outputFilePath = path.resolve(__dirname, `./output-${timeStamp}.json`) +fs.writeFileSync(outputFilePath, JSON.stringify({}, null, 2), 'utf8') + +function verifyToken(token) { + try { + const decoded = jwt.verify(token.trim(), process.env.ACCESS_TOKEN_SECRET) + + const isAdmin = (decoded?.data?.organizations || []).some((org) => + (org.roles || []).some((role) => role.title === 'admin') + ) + + if (!isAdmin) { + throw new Error('Unauthorized') + } + + return decoded + } catch (err) { + throw new Error('Unauthorized') + } +} + +function delay(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +function writeMigrationOutput(collectionName, outputData) { + let existingData = {} + + if (fs.existsSync(outputFilePath)) { + const fileContent = fs.readFileSync(outputFilePath, 'utf8') + existingData = fileContent ? JSON.parse(fileContent) : {} + } + + existingData[collectionName] = outputData + + fs.writeFileSync(outputFilePath, JSON.stringify(existingData, null, 2), 'utf8') +} + +async function migrateAssetCollections(db, collectionName) { + const collection = db.collection(collectionName) + + let query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + tenantMigrationReferenceId: { $exists: false }, + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + while (true) { + const doc = await cursor.next() + if (!doc) break + const newObjectId = new ObjectId() + let newDoc = { + ...doc, + _id: newObjectId, // generate new _id + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + tenantMigrationReferenceId: doc._id, + } + + if (collectionName == 'projectCategories') { + newDoc['visibleToOrganizations'] = [inputData.newOrgId.toString().trim()] + } + + batch.push({ + insertOne: { + document: newDoc, + }, + }) + outputData.data.push({ + _id: newObjectId.toString(), + migrationReferenceId: doc._id.toString(), + }) + + if (batch.length == BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateOrganizationExtension(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to delete: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + while (true) { + const doc = await cursor.next() + if (!doc) break + + batch.push({ + deleteOne: { + filter: { _id: doc._id }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length == BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateProjectTemplateTasks(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + while (true) { + const doc = await cursor.next() + if (!doc) break + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length == BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateCertificateTemplates(db, collectionName) { + const collection = db.collection(collectionName) + const baseTemplateCollection = db.collection('certificateBaseTemplates') + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + let newBaseTemplateId = null + if (doc.baseTemplateId) { + const baseTemplate = await baseTemplateCollection.findOne( + { + tenantMigrationReferenceId: doc.baseTemplateId, + }, + { projection: { _id: 1 } } + ) + + if (baseTemplate) { + newBaseTemplateId = baseTemplate._id + } + } + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + baseTemplateId: newBaseTemplateId, + }, + }, + }, + }) + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length == BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateProjectTemplates(db, collectionName) { + const collection = db.collection(collectionName) + const projectCategoriesCollection = db.collection('projectCategories') + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + /* -------------------------------------------------- + Build category reference map + oldCategoryId -> newCategoryId + ---------------------------------------------------*/ + const categoryDocs = await projectCategoriesCollection + .find( + { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + tenantMigrationReferenceId: { $exists: true }, + }, + { + projection: { + _id: 1, + tenantMigrationReferenceId: 1, + }, + } + ) + .toArray() + + const categoryMap = new Map() + + for (const cat of categoryDocs) { + categoryMap.set(cat.tenantMigrationReferenceId.toString(), cat._id) + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + let updatedCategories = [] + + if (Array.isArray(doc.categories)) { + updatedCategories = doc.categories.map((category) => { + const newCategoryId = categoryMap.get(category._id.toString()) + + return { + ...category, + _id: newCategoryId || category._id, + } + }) + } + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + categories: updatedCategories, + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +const entityDocuments = function ( + filterData = 'all', + projection = 'all', + page = null, + limit = null, + search = '', + aggregateValue = null, + isAggregateStaging = false, + isSort = true, + aggregateProjection = [] +) { + return new Promise(async (resolve, reject) => { + try { + // Function to find entity documents based on the given filter and projection + const url = + interfaceServiceUrl + + process.env.ENTITY_MANAGEMENT_SERVICE_BASE_URL + + '/v1/entities/find' + + `?page=${page}&limit=${limit}&search=${search}&aggregateValue=${aggregateValue}&aggregateStaging=${isAggregateStaging}&aggregateSort=${isSort}` + + if (filterData._id && Array.isArray(filterData._id) && filterData._id.length > 0) { + filterData['_id'] = { + $in: filterData._id, + } + } + + let requestJSON = { + query: filterData, + projection: projection, + aggregateProjection: aggregateProjection, + } + + // Set the options for the HTTP POST request + const options = { + headers: { + 'content-type': 'application/json', + 'internal-access-token': process.env.INTERNAL_ACCESS_TOKEN, + }, + json: requestJSON, + } + // Make the HTTP POST request to the entity management service + request.post(url, options, requestCallBack) + + // Callback function to handle the response from the HTTP POST request + function requestCallBack(err, data) { + let result = { + success: true, + } + + if (err) { + result.success = false + } else { + let response = data.body + // Check if the response status is OK (HTTP 200) + if (response.status === 200) { + result['data'] = response.result + } else { + result.success = false + } + } + + return resolve(result) + } + } catch (error) { + return reject(error) + } + }) +} + +async function migratePrograms(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + let scope = doc.scope || {} + + const scopeKeys = [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_subroles', + 'professional_role', + ] + + let updatedScope = { ...scope } + + for (const key of scopeKeys) { + if (!Array.isArray(scope[key]) || scope[key].length === 0) { + updatedScope[key] = scope[key] + continue + } else if (scope[key].includes('ALL')) { + updatedScope[key] = ['ALL'] + continue + } + + const result = await entityDocuments( + { + tenantId: inputData.newTenantId.toString().trim(), + 'metaInformation.tenantMigrationReferenceId': { $in: scope[key] }, + }, + { + _id: 1, + 'metaInformation.tenantMigrationReferenceId': 1, + } + ) + + if (result.success && result.data) { + const entityMap = new Map() + for (const entity of result.data) { + entityMap.set(entity.metaInformation.tenantMigrationReferenceId.toString(), entity._id.toString()) + } + + updatedScope[key] = scope[key].map((id) => entityMap.get(id.toString()) || id) + } + } + + updatedScope.organizations = [inputData.newOrgId.toString().trim()] + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + scope: updatedScope, + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateSolutions(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + let scope = doc.scope || {} + + const scopeKeys = [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_subroles', + 'professional_role', + ] + + let updatedScope = { ...scope } + + for (const key of scopeKeys) { + if (!Array.isArray(scope[key]) || scope[key].length === 0) { + updatedScope[key] = scope[key] + continue + } else if (scope[key].includes('ALL')) { + updatedScope[key] = ['ALL'] + continue + } + + const result = await entityDocuments( + { + tenantId: inputData.newTenantId.toString().trim(), + 'metaInformation.tenantMigrationReferenceId': { $in: scope[key] }, + }, + { + _id: 1, + 'metaInformation.tenantMigrationReferenceId': 1, + } + ) + + if (result.success && result.data) { + const entityMap = new Map() + + for (const entity of result.data) { + entityMap.set(entity.metaInformation.tenantMigrationReferenceId.toString(), entity._id.toString()) + } + + updatedScope[key] = scope[key].map((id) => entityMap.get(id.toString()) || id) + } + } + + updatedScope.organizations = [inputData.newOrgId.toString().trim()] + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + scope: updatedScope, + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function fetchUserProfile(userId, tenantId) { + return new Promise((resolve, reject) => { + const baseUrl = new URL(process.env.INTERFACE_SERVICE_URL) + const options = { + hostname: baseUrl.hostname, + port: baseUrl.port || 3567, + path: `${process.env.USER_SERVICE_BASE_URL}/v1/user/profileById/${userId}?tenant_code=${tenantId}`, + method: 'GET', + headers: { + internal_access_token: process.env.INTERNAL_ACCESS_TOKEN, + }, + } + + const req = http.request(options, (res) => { + let data = '' + + res.on('data', (chunk) => { + data += chunk + }) + + res.on('end', () => { + try { + const parsedData = JSON.parse(data) + resolve(parsedData) // โœ… store full response + } catch (err) { + reject(err) + } + }) + }) + + req.on('error', (err) => { + reject(err) + }) + + req.end() + }) +} + +async function pushToKafka(projectId, token, kafkaPushFailedProjects, kafkaPushSuccessProjects) { + return new Promise((resolve, reject) => { + const baseUrl = new URL(process.env.INTERFACE_SERVICE_URL) + + const options = { + hostname: baseUrl.hostname, + port: baseUrl.port, + path: `/project/v1/dataPipeline/pushProjectDetailsToKafka/${projectId}`, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json, text/plain, */*', + 'x-auth-token': token, + }, + } + + const req = http.request(options, (res) => { + let data = '' + + res.on('data', (chunk) => { + data += chunk + }) + + res.on('end', () => { + try { + if (res.statusCode >= 200 && res.statusCode < 300) { + console.log(`[Success] Project ${projectId} pushed to Kafka.`) + kafkaPushSuccessProjects.push(projectId) + resolve() + } else { + console.error(`[Failed] Project ${projectId} failed to push:`) + kafkaPushFailedProjects.push(projectId) + reject() + } + } catch (err) { + console.error(`[Parse Error] Project ${projectId}:`, err.message) + reject(err) + } + }) + }) + + req.on('error', (err) => { + console.error(`[Error] Project ${projectId}:`, err.message) + reject(err) + }) + + req.end() + }) +} + +async function migrateProjects(db, collectionName) { + const collection = db.collection(collectionName) + const programsCollection = db.collection('programs') + const solutionsCollection = db.collection('solutions') + const projectCategoriesCollection = db.collection('projectCategories') + let projectIdsToPushToKafka = [] + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + /* -------------------------------------------------- + Build category reference map + oldCategoryId -> newCategoryId + ---------------------------------------------------*/ + const categoryDocs = await projectCategoriesCollection + .find( + { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + tenantMigrationReferenceId: { $exists: true }, + }, + { + projection: { + _id: 1, + tenantMigrationReferenceId: 1, + }, + } + ) + .toArray() + + const categoryMap = new Map() + + for (const cat of categoryDocs) { + categoryMap.set(cat.tenantMigrationReferenceId.toString(), cat._id) + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + /* -------------------------- + Update categories + ---------------------------*/ + let updatedCategories = [] + + if (Array.isArray(doc.categories)) { + updatedCategories = doc.categories.map((category) => { + const newCategoryId = categoryMap.get(category._id.toString()) + + return { + ...category, + _id: newCategoryId || category._id, + } + }) + } + + /* -------------------------- + Update userRoleInformation + ---------------------------*/ + + let updatedUserRoleInformation = { ...(doc.userRoleInformation || {}) } + + const roleKeys = [ + 'state', + 'district', + 'block', + 'cluster', + 'school', + 'professional_role', + 'professional_subroles', + ] + + for (const key of roleKeys) { + if (!Array.isArray(updatedUserRoleInformation[key]) || updatedUserRoleInformation[key].length === 0) + continue + + const result = await entityDocuments( + { + tenantId: inputData.newTenantId.toString().trim(), + 'metaInformation.tenantMigrationReferenceId': { $in: updatedUserRoleInformation[key] }, + }, + { + _id: 1, + 'metaInformation.tenantMigrationReferenceId': 1, + } + ) + + if (result.success && result.data) { + const entityMap = new Map() + + for (const entity of result.data) { + entityMap.set(entity.metaInformation.tenantMigrationReferenceId.toString(), entity._id.toString()) + } + + updatedUserRoleInformation[key] = updatedUserRoleInformation[key].map( + (id) => entityMap.get(id.toString()) || id + ) + } + } + + updatedUserRoleInformation['organizations'] = [inputData.newOrgId.toString().trim()] + updatedUserRoleInformation['tenantId'] = inputData.newTenantId.toString().trim() + updatedUserRoleInformation['orgId'] = inputData.newOrgId.toString().trim() + + /* -------------------------- + Update entity-information + ---------------------------*/ + let updatedEntityInformation = doc.entityInformation + let updatedEntityId = '' + + if (doc.entityInformation && doc.entityInformation._id && doc.entityInformation._id != '') { + const result = await entityDocuments( + { + tenantId: inputData.newTenantId.toString().trim(), + 'metaInformation.tenantMigrationReferenceId': doc.entityInformation._id, + }, + { + _id: 1, + 'metaInformation.tenantMigrationReferenceId': 1, + } + ) + + if (result.success && result.data) { + updatedEntityInformation._id = result.data[0]._id + } + } + + if (doc.entityId && doc.entityId != '') { + const result = await entityDocuments( + { + tenantId: inputData.newTenantId.toString().trim(), + 'metaInformation.tenantMigrationReferenceId': doc.entityInformation._id, + }, + { + _id: 1, + 'metaInformation.tenantMigrationReferenceId': 1, + } + ) + + if (result.success && result.data) { + updatedEntityId = result.data[0]._id + } + } + + /* -------------------------- + Update user-profile + ---------------------------*/ + + let updatedUserProfile = await fetchUserProfile(doc.userId, inputData.newTenantId.toString().trim()) + + /* -------------------------- + Update program-information + ---------------------------*/ + + let updatedProgramInformation = await programsCollection.findOne({ + _id: new ObjectId(doc.programId), + tenantId: inputData.newTenantId.toString().trim(), + }) + + /* -------------------------- + Update solution-information + ---------------------------*/ + let updatedSolutionInformation = await solutionsCollection.findOne({ + _id: new ObjectId(doc.solutionId), + tenantId: inputData.newTenantId.toString().trim(), + }) + + projectIdsToPushToKafka.push(doc._id.toString()) + + /* -------------------------- + Update tasks + ---------------------------*/ + let updatedTasks = [] + + if (Array.isArray(doc.tasks)) { + updatedTasks = doc.tasks.map((task) => ({ + ...task, + tenantId: inputData.newTenantId.toString().trim(), + orgIds: [inputData.newOrgId.toString().trim()], + orgId: inputData.newOrgId.toString().trim(), + })) + } + + /* -------------------------- + Add to batch + ---------------------------*/ + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + categories: updatedCategories, + userRoleInformation: updatedUserRoleInformation, + entityInformation: updatedEntityInformation, + entityId: updatedEntityId, + userProfile: updatedUserProfile.result, + programInformation: updatedProgramInformation, + solutionInformation: updatedSolutionInformation, + tasks: updatedTasks, + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + // Push projects to Kafka + for (const projectId of projectIdsToPushToKafka) { + await pushToKafka( + projectId, + inputData.token.toString().trim(), + kafkaPushFailedProjects, + kafkaPushSuccessProjects + ) + await delay(1000) + } + + writeMigrationOutput('kafkaPushSuccessProjects', kafkaPushSuccessProjects) + writeMigrationOutput('kafkaPushFailedProjects', kafkaPushFailedProjects) + writeMigrationOutput(collectionName, outputData) +} + +async function migrateUserCourses(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgId: inputData.currentOrgId.toString().trim(), + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + /* -------------------------- + Update user-profile + ---------------------------*/ + + let updatedUserProfile = await fetchUserProfile(doc.userId, inputData.newTenantId.toString().trim()) + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgId: inputData.newOrgId.toString().trim(), + userProfile: updatedUserProfile.result, + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function migrateUserExtensions(db, collectionName) { + const collection = db.collection(collectionName) + + const query = { + tenantId: inputData.currentTenantId.toString().trim(), + orgIds: { $in: [inputData.currentOrgId.toString().trim()] }, + } + + const totalDocs = await collection.countDocuments(query) + console.log(`๐Ÿ“Š Documents to migrate: ${totalDocs}`) + + let outputData = { + data: [], + count: totalDocs, + } + + const cursor = collection.find(query).batchSize(BATCH_SIZE) + + let batch = [] + + while (true) { + const doc = await cursor.next() + if (!doc) break + + batch.push({ + updateOne: { + filter: { _id: doc._id }, + update: { + $set: { + tenantId: inputData.newTenantId.toString().trim(), + orgIds: [inputData.newOrgId.toString().trim()], + }, + }, + }, + }) + + outputData.data.push({ + _id: doc._id.toString(), + migrationReferenceId: 'N/A', + }) + + if (batch.length === BATCH_SIZE) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + } + + if (batch.length) { + await collection.bulkWrite(batch, { ordered: false }) + batch = [] + await delay(3000) + } + + writeMigrationOutput(collectionName, outputData) +} + +async function runMigration() { + const client = await MongoClient.connect(MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true }) + + try { + verifyToken(inputData.token.trim()) + await client.connect() + console.log('๐Ÿ”Œ Connected to MongoDB') + + const db = client.db() + + for (const collectionName of collections) { + console.log(`\n๐Ÿš€ Starting migration for: ${collectionName}`) + switch (collectionName) { + case 'certificateBaseTemplates': + await migrateAssetCollections(db, collectionName) + break + + case 'projectCategories': + await migrateAssetCollections(db, collectionName) + break + + case 'organizationExtension': + await migrateOrganizationExtension(db, collectionName) + break + + case 'programs': + await migratePrograms(db, collectionName) + break + + case 'solutions': + await migrateSolutions(db, collectionName) + break + + case 'projectTemplateTasks': + await migrateProjectTemplateTasks(db, collectionName) + break + + case 'certificateTemplates': + await migrateCertificateTemplates(db, collectionName) + break + + case 'projectTemplates': + await migrateProjectTemplates(db, collectionName) + break + + case 'projects': + await migrateProjects(db, collectionName) + break + + case 'userCourses': + await migrateUserCourses(db, collectionName) + break + + case 'userExtension': + await migrateUserExtensions(db, collectionName) + break + } + console.log(`๐ŸŽ‰ Completed migration for: ${collectionName}`) + } + + console.log('\n๐Ÿ Migration completed successfully.') + } catch (error) { + console.error('โŒ Migration failed:', error) + } finally { + await client.close() + console.log('๐Ÿ”’ Connection closed') + process.exit(1) + } +} + +runMigration() diff --git a/module/admin/helper.js b/module/admin/helper.js index 0a93e47c..75c7b13d 100644 --- a/module/admin/helper.js +++ b/module/admin/helper.js @@ -152,7 +152,7 @@ module.exports = class AdminHelper { * @param {String} [deletedBy='SYSTEM'] - User ID or system name that triggered the deletion. * @param {String} userToken - Auth token used for downstream service calls (e.g., survey service). * - * @returns {Promise} - Result object summarizing deletion impact. + * @returns {Promise} - Result object summarizing deletion impact with IDs and counts. */ static deletedResourceDetails( resourceId, @@ -164,18 +164,27 @@ module.exports = class AdminHelper { ) { return new Promise(async (resolve, reject) => { try { - // Track deletion counts for all associated resources - let deletedProgramsCount = 0 - let deletedSolutionsCount = 0 - let deletedProjectTemplatesCount = 0 - let deletedCertificateTemplatesCount = 0 - let deletedProjectTemplateTasksCount = 0 - let deletedSurveysCount = 0 - let deletedSurveySubmissionsCount = 0 - let deletedObservationsCount = 0 - let deletedObservationSubmissionsCount = 0 + // Track deletion IDs and counts for all associated resources + let deletedPrograms = { deletedProgramsIds: [], deletedProgramsCount: 0 } + let deletedSolutions = { deletedSolutionsIds: [], deletedSolutionsCount: 0 } + let deletedProjectTemplates = { deletedProjectTemplatesIds: [], deletedProjectTemplatesCount: 0 } + let deletedCertificateTemplates = { + deletedCertificateTemplatesIds: [], + deletedCertificateTemplatesCount: 0, + } + let deletedProjectTemplateTasks = { + deletedProjectTemplateTasksIds: [], + deletedProjectTemplateTasksCount: 0, + } + let deletedSurveys = { deletedSurveysIds: [], deletedSurveysCount: 0 } + let deletedSurveySubmissions = { deletedSurveySubmissionsIds: [], deletedSurveySubmissionsCount: 0 } + let deletedObservations = { deletedObservationsIds: [], deletedObservationsCount: 0 } + let deletedObservationSubmissions = { + deletedObservationSubmissionsIds: [], + deletedObservationSubmissionsCount: 0, + } + let deletedProjects = { deletedProjectsIds: [], deletedProjectsCount: 0 } let pullProgramFromUserExtensionCount = 0 - let deletedProjectsCount = 0 // Track all resource IDs deleted for audit logging let resourceIdsWithType = [] @@ -207,12 +216,9 @@ module.exports = class AdminHelper { } } - // Initialize projectTemplate and solution ID holders - let projectTemplateIds - let solutionIds if (programDetails[0].components) { // Extract solution IDs from program components - solutionIds = programDetails[0].components.map((component) => component._id) + const solutionIds = programDetails[0].components.map((component) => component._id) const solutionFilter = { _id: { $in: solutionIds }, @@ -236,77 +242,127 @@ module.exports = class AdminHelper { CONSTANTS.common.SOLUTION, tenantId, orgId, - deletedBy + deletedBy, + isAPrivateProgram ) - deletedSurveysCount += deleteResponse.data.result.deletedSurveysCount || 0 - deletedSurveySubmissionsCount += - deleteResponse.data.result.deletedSurveySubmissionsCount || 0 - deletedObservationsCount += deleteResponse.data.result.deletedObservationsCount || 0 - deletedObservationSubmissionsCount += - deleteResponse.data.result.deletedObservationSubmissionsCount || 0 + const surveyData = deleteResponse.data.result + // IDs will be populated once samiksha returns them; counts always merged + deletedSurveys.deletedSurveysIds.push(...(surveyData.deletedSurveysIds || [])) + deletedSurveys.deletedSurveysCount += surveyData.deletedSurveysCount || 0 + deletedSurveySubmissions.deletedSurveySubmissionsIds.push( + ...(surveyData.deletedSurveySubmissionsIds || []) + ) + deletedSurveySubmissions.deletedSurveySubmissionsCount += + surveyData.deletedSurveySubmissionsCount || 0 + deletedObservations.deletedObservationsIds.push( + ...(surveyData.deletedObservationsIds || []) + ) + deletedObservations.deletedObservationsCount += surveyData.deletedObservationsCount || 0 + deletedObservationSubmissions.deletedObservationSubmissionsIds.push( + ...(surveyData.deletedObservationSubmissionsIds || []) + ) + deletedObservationSubmissions.deletedObservationSubmissionsCount += + surveyData.deletedObservationSubmissionsCount || 0 + deletedSolutions.deletedSolutionsIds.push(...(surveyData.deletedSolutionsIds || [])) + deletedSolutions.deletedSolutionsCount += surveyData.deletedSolutionsCount || 0 } - const deletedSolutions = await solutionsQueries.delete(solutionFilter) - deletedSolutionsCount += deletedSolutions.deletedCount || 0 - if (solutionIds && solutionIds.length) { - for (const Id of solutionIds) { - resourceIdsWithType.push({ id: Id, type: CONSTANTS.common.SOLUTION }) - } - } - // Extract project template IDs from solutions - projectTemplateIds = solutionDetails.map((solution) => { - return solution.projectTemplateId - }) + // Delete solutions from project service + await solutionsQueries.delete(solutionFilter) + deletedSolutions.deletedSolutionsIds.push(...solutionIds.map((id) => id.toString())) + deletedSolutions.deletedSolutionsCount += solutionIds.length - // Add main program ID to deletion list + // Audit log entries for solutions + solutionIds.forEach((id) => resourceIdsWithType.push({ id, type: CONSTANTS.common.SOLUTION })) + + // Audit log entry for the program itself resourceIdsWithType.push({ id: resourceId, type: CONSTANTS.common.PROGRAM }) - if (solutionIds && solutionIds.length > 0) { - // Delete all projects linked to the solutions - let projecFilter = { - solutionId: { $in: solutionIds }, - isAPrivateProgram: false, - tenantId: tenantId, - } - let deletedProjectIds = await projectQueries.delete(projecFilter) - deletedProjectsCount = deletedProjectIds.deletedCount + // Delete all projects linked to these solutions + // Fetch IDs first since deleteMany does not return them + const projectFilter = { + solutionId: { $in: solutionIds }, + isAPrivateProgram: false, + tenantId, + } + const projectsToDelete = await projectQueries.projectDocument(projectFilter, ['_id']) + if (projectsToDelete && projectsToDelete.length > 0) { + deletedProjects.deletedProjectsIds = projectsToDelete.map((p) => p._id.toString()) + await projectQueries.delete(projectFilter) + deletedProjects.deletedProjectsCount = deletedProjects.deletedProjectsIds.length } + // Remove program ID from user extension's programRoleMapping const programObjectId = typeof resourceId === 'string' ? new ObjectId(resourceId) : resourceId - let programRoleMappingId = await userExtensionQueries.pullProgramIdFromProgramRoleMapping( + const programRoleMappingResult = await userExtensionQueries.pullProgramIdFromProgramRoleMapping( programObjectId, tenantId ) - // Delete all associated entities tied to projectTemplateIds - pullProgramFromUserExtensionCount = programRoleMappingId.nModified || 0 + pullProgramFromUserExtensionCount = programRoleMappingResult.nModified || 0 // Delete all associated resources for collected projectTemplateIds + const projectTemplateIds = solutionDetails + .map((solution) => solution.projectTemplateId) + .filter(Boolean) + if (projectTemplateIds.length > 0) { const result = await this.deleteAssociatedResources( projectTemplateIds, tenantId, orgId, - deletedBy + deletedBy, + isAPrivateProgram ) if (result.success) { - deletedProjectTemplatesCount += result.result.deletedProjectTemplatesCount - deletedCertificateTemplatesCount += result.result.deletedCertificateTemplatesCount - deletedProjectTemplateTasksCount += result.result.deletedProjectTemplateTasksCount - deletedSurveysCount += result.result.deletedSurveysCount - deletedSurveySubmissionsCount += result.result.deletedSurveySubmissionsCount - deletedObservationsCount += result.result.deletedObservationsCount - deletedObservationSubmissionsCount += result.result.deletedObservationSubmissionsCount + const associateResourceData = result.result + deletedProjectTemplates.deletedProjectTemplatesIds.push( + ...associateResourceData.deletedProjectTemplates.deletedProjectTemplatesIds + ) + deletedProjectTemplates.deletedProjectTemplatesCount += + associateResourceData.deletedProjectTemplates.deletedProjectTemplatesCount + deletedCertificateTemplates.deletedCertificateTemplatesIds.push( + ...associateResourceData.deletedCertificateTemplates.deletedCertificateTemplatesIds + ) + deletedCertificateTemplates.deletedCertificateTemplatesCount += + associateResourceData.deletedCertificateTemplates.deletedCertificateTemplatesCount + deletedProjectTemplateTasks.deletedProjectTemplateTasksIds.push( + ...associateResourceData.deletedProjectTemplateTasks.deletedProjectTemplateTasksIds + ) + deletedProjectTemplateTasks.deletedProjectTemplateTasksCount += + associateResourceData.deletedProjectTemplateTasks.deletedProjectTemplateTasksCount + deletedSurveys.deletedSurveysIds.push( + ...associateResourceData.deletedSurveys.deletedSurveysIds + ) + deletedSurveys.deletedSurveysCount += + associateResourceData.deletedSurveys.deletedSurveysCount + deletedSurveySubmissions.deletedSurveySubmissionsIds.push( + ...associateResourceData.deletedSurveySubmissions.deletedSurveySubmissionsIds + ) + deletedSurveySubmissions.deletedSurveySubmissionsCount += + associateResourceData.deletedSurveySubmissions.deletedSurveySubmissionsCount + deletedObservations.deletedObservationsIds.push( + ...associateResourceData.deletedObservations.deletedObservationsIds + ) + deletedObservations.deletedObservationsCount += + associateResourceData.deletedObservations.deletedObservationsCount + deletedObservationSubmissions.deletedObservationSubmissionsIds.push( + ...associateResourceData.deletedObservationSubmissions + .deletedObservationSubmissionsIds + ) + deletedObservationSubmissions.deletedObservationSubmissionsCount += + associateResourceData.deletedObservationSubmissions.deletedObservationSubmissionsCount } } } // Delete the program itself await programsQueries.delete(programFilter) - deletedProgramsCount++ - // Publish Kafka event - // { + deletedPrograms.deletedProgramsIds.push(resourceId.toString()) + deletedPrograms.deletedProgramsCount++ + + // Publish Kafka event// { // "topic": "RESOURCE_DELETION_TOPIC", // "messages": "{\"entity\":\"resource\",\"type\":\"program\",\"eventType\":\"delete\",\"entityId\":\"682c1526ba875600144d93bc\",\"deleted_By\":1,\"tenant_code\":\"shikshagraha\",\"organization_id\":[\"blr\"]}" // } @@ -324,17 +380,17 @@ module.exports = class AdminHelper { success: true, message: CONSTANTS.apiResponses.PROGRAM_RESOURCE_DELETED, result: { - deletedProgramsCount, - deletedSolutionsCount, - deletedProjectTemplatesCount, - deletedCertificateTemplatesCount, - deletedProjectTemplateTasksCount, - deletedSurveysCount, - deletedSurveySubmissionsCount, - deletedObservationsCount, - deletedObservationSubmissionsCount, + deletedPrograms, + deletedSolutions, + deletedProjectTemplates, + deletedCertificateTemplates, + deletedProjectTemplateTasks, + deletedSurveys, + deletedSurveySubmissions, + deletedObservations, + deletedObservationSubmissions, pullProgramFromUserExtensionCount, - deletedProjectsCount, + deletedProjects, }, }) } else if (resourceType === CONSTANTS.common.SOLUTION) { @@ -353,26 +409,28 @@ module.exports = class AdminHelper { message: CONSTANTS.apiResponses.SOLUTION_NOT_FOUND, } } - // Delete projects linked to the solution - let projecFilter = { + // Fetch project IDs before deleting + const projectFilter = { solutionId: { $in: [resourceId] }, isAPrivateProgram: false, - tenantId: tenantId, + tenantId, + } + const projectsToDelete = await projectQueries.projectDocument(projectFilter, ['_id']) + if (projectsToDelete && projectsToDelete.length > 0) { + deletedProjects.deletedProjectsIds = projectsToDelete.map((p) => p._id.toString()) + await projectQueries.delete(projectFilter) + deletedProjects.deletedProjectsCount = deletedProjects.deletedProjectsIds.length } - let deletedProjectIds = await projectQueries.delete(projecFilter) - deletedProjectsCount = deletedProjectIds.deletedCount // Remove the solution reference from parent program - const solutionId = new ObjectId(resourceId) - await programsQueries.pullSolutionsFromComponents(solutionId, tenantId) + const solutionObjectId = new ObjectId(resourceId) + await programsQueries.pullSolutionsFromComponents(solutionObjectId, tenantId) - const deletedSolutions = await solutionsQueries.delete(solutionFilter) - deletedSolutionsCount += deletedSolutions.deletedCount || 0 - // Push event to kafka - // { - // "topic": "RESOURCE_DELETION_TOPIC", - // "messages": "{\"entity\":\"resource\",\"type\":\"solution\",\"eventType\":\"delete\",\"entityId\":\"682c1526ba875600144d93bc\",\"deleted_By\":1,\"tenant_code\":\"shikshagraha\",\"organization_id\":[\"blr\"]}" - // } + await solutionsQueries.delete(solutionFilter) + deletedSolutions.deletedSolutionsIds.push(resourceId.toString()) + deletedSolutions.deletedSolutionsCount++ + + // Publish Kafka event for solution deletion await this.pushResourceDeleteKafkaEvent('solution', resourceId, deletedBy, tenantId, orgId) resourceIdsWithType.push({ id: resourceId, type: CONSTANTS.common.SOLUTION }) @@ -383,17 +441,47 @@ module.exports = class AdminHelper { [solutionDetails[0].projectTemplateId], tenantId, orgId, - deletedBy + deletedBy, + isAPrivateProgram ) if (result.success) { - deletedProjectTemplatesCount += result.result.deletedProjectTemplatesCount - deletedCertificateTemplatesCount += result.result.deletedCertificateTemplatesCount - deletedProjectTemplateTasksCount += result.result.deletedProjectTemplateTasksCount - deletedSurveysCount += result.result.deletedSurveysCount - deletedSurveySubmissionsCount += result.result.deletedSurveySubmissionsCount - deletedObservationsCount += result.result.deletedObservationsCount - deletedObservationSubmissionsCount += result.result.deletedObservationSubmissionsCount + const associateResourceData = result.result + deletedProjectTemplates.deletedProjectTemplatesIds.push( + ...associateResourceData.deletedProjectTemplates.deletedProjectTemplatesIds + ) + deletedProjectTemplates.deletedProjectTemplatesCount += + associateResourceData.deletedProjectTemplates.deletedProjectTemplatesCount + deletedCertificateTemplates.deletedCertificateTemplatesIds.push( + ...associateResourceData.deletedCertificateTemplates.deletedCertificateTemplatesIds + ) + deletedCertificateTemplates.deletedCertificateTemplatesCount += + associateResourceData.deletedCertificateTemplates.deletedCertificateTemplatesCount + deletedProjectTemplateTasks.deletedProjectTemplateTasksIds.push( + ...associateResourceData.deletedProjectTemplateTasks.deletedProjectTemplateTasksIds + ) + deletedProjectTemplateTasks.deletedProjectTemplateTasksCount += + associateResourceData.deletedProjectTemplateTasks.deletedProjectTemplateTasksCount + deletedSurveys.deletedSurveysIds.push( + ...associateResourceData.deletedSurveys.deletedSurveysIds + ) + deletedSurveys.deletedSurveysCount += + associateResourceData.deletedSurveys.deletedSurveysCount + deletedSurveySubmissions.deletedSurveySubmissionsIds.push( + ...associateResourceData.deletedSurveySubmissions.deletedSurveySubmissionsIds + ) + deletedSurveySubmissions.deletedSurveySubmissionsCount += + associateResourceData.deletedSurveySubmissions.deletedSurveySubmissionsCount + deletedObservations.deletedObservationsIds.push( + ...associateResourceData.deletedObservations.deletedObservationsIds + ) + deletedObservations.deletedObservationsCount += + associateResourceData.deletedObservations.deletedObservationsCount + deletedObservationSubmissions.deletedObservationSubmissionsIds.push( + ...associateResourceData.deletedObservationSubmissions.deletedObservationSubmissionsIds + ) + deletedObservationSubmissions.deletedObservationSubmissionsCount += + associateResourceData.deletedObservationSubmissions.deletedObservationSubmissionsCount } } @@ -402,15 +490,15 @@ module.exports = class AdminHelper { success: true, message: CONSTANTS.apiResponses.SOLUTION_RESOURCE_DELETED, result: { - deletedSolutionsCount, - deletedProjectTemplatesCount, - deletedCertificateTemplatesCount, - deletedProjectTemplateTasksCount, - deletedSurveysCount, - deletedSurveySubmissionsCount, - deletedObservationsCount, - deletedObservationSubmissionsCount, - deletedProjectsCount, + deletedSolutions, + deletedProjectTemplates, + deletedCertificateTemplates, + deletedProjectTemplateTasks, + deletedSurveys, + deletedSurveySubmissions, + deletedObservations, + deletedObservationSubmissions, + deletedProjects, }, }) } else { @@ -437,26 +525,35 @@ module.exports = class AdminHelper { * @param {string} tenantId - Tenant identifier. * @param {string} orgId - Organization identifier. * @param {string} deletedBy - Auth token for downstream service calls. + * @param {Boolean} isAPrivateProgram - If Program is Private `true` else `false`. */ - static deleteAssociatedResources(projectTemplateIds, tenantId, orgId, deletedBy) { + static deleteAssociatedResources(projectTemplateIds, tenantId, orgId, deletedBy, isAPrivateProgram) { return new Promise(async (resolve, reject) => { try { - // Initialize counters to track deletions - let deletedProjectTemplatesCount = 0 - let deletedCertificateTemplatesCount = 0 - let deletedProjectTemplateTasksCount = 0 - let deletedSurveysCount = 0 - let deletedSurveySubmissionsCount = 0 - let deletedObservationsCount = 0 - let deletedObservationSubmissionsCount = 0 - - // Prepare the filter to fetch matching project templates + // Track IDs and counts for each resource type + let deletedProjectTemplates = { deletedProjectTemplatesIds: [], deletedProjectTemplatesCount: 0 } + let deletedCertificateTemplates = { + deletedCertificateTemplatesIds: [], + deletedCertificateTemplatesCount: 0, + } + let deletedProjectTemplateTasks = { + deletedProjectTemplateTasksIds: [], + deletedProjectTemplateTasksCount: 0, + } + let deletedSurveys = { deletedSurveysIds: [], deletedSurveysCount: 0 } + let deletedSurveySubmissions = { deletedSurveySubmissionsIds: [], deletedSurveySubmissionsCount: 0 } + let deletedObservations = { deletedObservationsIds: [], deletedObservationsCount: 0 } + let deletedObservationSubmissions = { + deletedObservationSubmissionsIds: [], + deletedObservationSubmissionsCount: 0, + } + const projectTemplateFilter = { _id: { $in: projectTemplateIds }, - tenantId: tenantId, + tenantId, } - // Fetch project templates along with associated tasks and certificates + // Fetch project templates with tasks and certificate references const projectTemplateDetails = await projectTemplateQueries.templateDocument(projectTemplateFilter, [ 'tasks', 'certificateTemplateId', @@ -472,17 +569,19 @@ module.exports = class AdminHelper { // Delete all fetched project templates await projectTemplateQueries.delete(projectTemplateFilter) - deletedProjectTemplatesCount = projectTemplateDetails.length + deletedProjectTemplates.deletedProjectTemplatesIds = projectTemplateDetails.map((t) => t._id.toString()) + deletedProjectTemplates.deletedProjectTemplatesCount = + deletedProjectTemplates.deletedProjectTemplatesIds.length - // If any certificate templates are associated, delete them + // Delete certificate templates if (certificateTemplateIds.length > 0) { - const certificateTemplateFilter = { - _id: { $in: certificateTemplateIds }, - tenantId: tenantId, - } - - let certificateTemplateDetails = await certificateTemplateQueries.delete(certificateTemplateFilter) - deletedCertificateTemplatesCount = certificateTemplateDetails.deletedCount + const certificateTemplateFilter = { _id: { $in: certificateTemplateIds }, tenantId } + await certificateTemplateQueries.delete(certificateTemplateFilter) + deletedCertificateTemplates.deletedCertificateTemplatesIds = certificateTemplateIds.map((id) => + id.toString() + ) + deletedCertificateTemplates.deletedCertificateTemplatesCount = + deletedCertificateTemplates.deletedCertificateTemplatesIds.length } // If any tasks exist, fetch and delete them @@ -509,32 +608,47 @@ module.exports = class AdminHelper { CONSTANTS.common.SOLUTION, tenantId, orgId, - deletedBy + deletedBy, + isAPrivateProgram ) - - deletedSurveysCount += deleteResponse.data.result.deletedSurveysCount || 0 - deletedSurveySubmissionsCount += deleteResponse.data.result.deletedSurveySubmissionsCount || 0 - deletedObservationsCount += deleteResponse.data.result.deletedObservationsCount || 0 - deletedObservationSubmissionsCount += - deleteResponse.data.result.deletedObservationSubmissionsCount || 0 + const surveyData = deleteResponse.data.result + // IDs populated once samiksha returns them; counts always merged + deletedSurveys.deletedSurveysIds.push(...(surveyData.deletedSurveysIds || [])) + deletedSurveys.deletedSurveysCount += surveyData.deletedSurveysCount || 0 + deletedSurveySubmissions.deletedSurveySubmissionsIds.push( + ...(surveyData.deletedSurveySubmissionsIds || []) + ) + deletedSurveySubmissions.deletedSurveySubmissionsCount += + surveyData.deletedSurveySubmissionsCount || 0 + deletedObservations.deletedObservationsIds.push(...(surveyData.deletedObservationsIds || [])) + deletedObservations.deletedObservationsCount += surveyData.deletedObservationsCount || 0 + deletedObservationSubmissions.deletedObservationSubmissionsIds.push( + ...(surveyData.deletedObservationSubmissionsIds || []) + ) + deletedObservationSubmissions.deletedObservationSubmissionsCount += + surveyData.deletedObservationSubmissionsCount || 0 } - // Delete the project template tasks + // Delete tasks and record their IDs await projectTemplateTaskQueries.delete(taskFilter) - deletedProjectTemplateTasksCount = taskDetails.length + deletedProjectTemplateTasks.deletedProjectTemplateTasksIds = taskDetails.map((t) => + t._id.toString() + ) + deletedProjectTemplateTasks.deletedProjectTemplateTasksCount = + deletedProjectTemplateTasks.deletedProjectTemplateTasksIds.length } return resolve({ success: true, message: 'Associated resources deleted successfully', result: { - deletedProjectTemplatesCount, - deletedCertificateTemplatesCount, - deletedProjectTemplateTasksCount, - deletedSurveysCount, - deletedSurveySubmissionsCount, - deletedObservationsCount, - deletedObservationSubmissionsCount, + deletedProjectTemplates, + deletedCertificateTemplates, + deletedProjectTemplateTasks, + deletedSurveys, + deletedSurveySubmissions, + deletedObservations, + deletedObservationSubmissions, }, }) } catch (error) {