diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 074726e..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: CI - -on: - push: - branches: - - master - pull_request: - -concurrency: - group: master-checktrack_connector-${{ github.event.number }} - cancel-in-progress: true - -jobs: - tests: - runs-on: ubuntu-latest - strategy: - fail-fast: false - name: Server - - services: - redis-cache: - image: redis:alpine - ports: - - 13000:6379 - redis-queue: - image: redis:alpine - ports: - - 11000:6379 - mariadb: - image: mariadb:10.6 - env: - MYSQL_ROOT_PASSWORD: root - ports: - - 3306:3306 - options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3 - - steps: - - name: Clone - uses: actions/checkout@v3 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 18 - check-latest: true - - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }} - restore-keys: | - ${{ runner.os }}-pip- - ${{ runner.os }}- - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: 'echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT' - - - uses: actions/cache@v4 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Install MariaDB Client - run: sudo apt-get install -y mariadb-client - - - name: Setup - run: | - pip install frappe-bench - bench init --skip-redis-config-generation --skip-assets --python "$(which python)" ~/frappe-bench - mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'" - mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" - - name: Install - working-directory: /home/runner/frappe-bench - run: | - bench get-app checktrack_connector $GITHUB_WORKSPACE - bench setup requirements --dev - bench new-site --db-root-password root --admin-password admin test_site - bench --site test_site install-app checktrack_connector - bench build - env: - CI: 'Yes' - - - name: Run Tests - working-directory: /home/runner/frappe-bench - run: | - bench --site test_site set-config allow_tests true - bench --site test_site run-tests --app checktrack_connector - env: - TYPE: server \ No newline at end of file diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index 3f418ba..0000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Linters - -on: - pull_request: - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - linter: - name: 'Frappe Linter' - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.10' - cache: pip - - uses: pre-commit/action@v3.0.0 - - - name: Download Semgrep rules - run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules - - - name: Run Semgrep rules - run: | - pip install semgrep - semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness - deps-vulnerable-check: - name: 'Vulnerable Dependency Check' - runs-on: ubuntu-latest - - steps: - - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - - uses: actions/checkout@v4 - - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py') }} - restore-keys: | - ${{ runner.os }}-pip- - ${{ runner.os }}- - - name: Install and run pip-audit - run: | - pip install pip-audit - cd ${GITHUB_WORKSPACE} - pip-audit --desc on . \ No newline at end of file diff --git a/checktrack_connector/api.py b/checktrack_connector/api.py index ab5ce9a..979a43f 100644 --- a/checktrack_connector/api.py +++ b/checktrack_connector/api.py @@ -720,12 +720,14 @@ def check_tenant_exists(email): # Step 1: Get access token using hardcoded credentials auth_url = f"{USER_API_URL}/login" + admin_email = conf.get("checktrack_admin_email") + admin_password = conf.get("checktrack_admin_password") auth_payload = { - "email": "jaympatel9294@gmail.com", - "password": "0hr3VuNoyqcgy1Su" + "email": admin_email, + "password": admin_password } HEADERS = {"Content-Type": "application/json"} - + try: auth_response = requests.post(auth_url, headers=HEADERS, json=auth_payload) @@ -752,7 +754,7 @@ def check_tenant_exists(email): if not employee.get("company"): return {"exists": False, "message": "Employee has no associated company."} - + # Step 4: Get tenant_id from Company doctype tenant_id = frappe.db.get_value("Company", employee.get("company"), "tenant_id") diff --git a/checktrack_connector/checktrack_connector/doctype/checktrack_integration/checktrack_integration.js b/checktrack_connector/checktrack_connector/doctype/checktrack_integration/checktrack_integration.js index 2ff93ed..666dcca 100644 --- a/checktrack_connector/checktrack_connector/doctype/checktrack_integration/checktrack_integration.js +++ b/checktrack_connector/checktrack_connector/doctype/checktrack_integration/checktrack_integration.js @@ -7,20 +7,24 @@ frappe.ui.form.on('CheckTrack Integration', { frm.page.btn_primary.hide(); } if (!frm.is_new()) { + showConnectionLoader(frm); check_tenant_exists(frm, function(exists) { + hideConnectionLoader(frm); + if (exists) { - frm.fields.forEach(field => { - frm.set_df_property(field.df.fieldname, 'hidden', true); + if (field.df.fieldname !== 'name') { // Keep the name field visible + frm.set_df_property(field.df.fieldname, 'hidden', true); + } }); + frm.dashboard.clear_headline(); frm.dashboard.set_headline( `
${__("Connected to Checktrack")}
` ); - frm.set_indicator(__('Connected to Frappe'), 'green'); frm.remove_custom_button('Connect'); } else { @@ -131,11 +135,11 @@ frappe.ui.form.on('CheckTrack Integration', { if (response.message) { if (response.message.is_fully_integration) { - frappe.msgprint(__('Checktrack successfully integration.')); + frappe.msgprint(__('Checktrack successfully integrated.')); frm.reload_doc(); } } else { - frappe.msgprint(__('Failed to integrat!')); + frappe.msgprint(__('Failed to integrate!')); } }) .catch((error) => { @@ -162,22 +166,78 @@ frappe.ui.form.on('CheckTrack Integration', { }); function check_tenant_exists(frm, callback) { - frappe.call({ - method: 'checktrack_connector.api.check_tenant_exists', + method: 'frappe.client.get_value', args: { - email: frappe.session.user + doctype: 'User', + filters: { name: frappe.session.user }, + fieldname: 'email' }, - callback: function (response) { - var exists = response.message && response.message.exists; - if (callback) callback(exists); + callback: function (r) { + const userEmail = r.message.email; + console.log("check_tenant_exists called with email:", userEmail); + + frappe.call({ + method: 'checktrack_connector.api.check_tenant_exists', + args: { + email: userEmail + }, + callback: function (response) { + console.log("check_tenant_exists API response:", response); + var exists = response.message && response.message.exists; + console.log("Extracted exists value:", exists); + if (callback) callback(exists); + }, + error: function(err) { + console.error("Error checking tenant exists:", err); + if (callback) callback(false); + } + }); }, error: function(err) { - console.error("Error checking tenant exists:", err); + console.error("Error getting user email:", err); if (callback) callback(false); } }); } +function showConnectionLoader(frm) { + if (frm.fields_dict.email) { + frm.set_df_property('email', 'hidden', true); + } + if (frm.fields_dict.password) { + frm.set_df_property('password', 'hidden', true); + } + + frm.dashboard.clear_headline(); + frm.dashboard.set_headline( + `
+
+ Loading... +
+
+ ${__("Checking connection status...")} +
+
` + ); + + frm.disable_save(); +} + + +function hideConnectionLoader(frm) { + if (frm.fields_dict.email) { + frm.set_df_property('email', 'hidden', false); + } + if (frm.fields_dict.password) { + frm.set_df_property('password', 'hidden', false); + } + + frm.dashboard.clear_headline(); + + frm.enable_save(); +} + + diff --git a/checktrack_connector/onboard_api.py b/checktrack_connector/onboard_api.py index 87087ed..392a326 100644 --- a/checktrack_connector/onboard_api.py +++ b/checktrack_connector/onboard_api.py @@ -92,7 +92,7 @@ def automated_import_users(tenant_id=None, integration_email=None): # Check if we have any data to import (excluding header) if len(data) <= 1: return { - "status": "warning", + "status": "success", "message": f"No users to import after skipping integration email(s). Skipped {skipped_count} email(s)." } @@ -235,6 +235,11 @@ def import_project(tenant_id, tenant_prefix, access_token,company_name): projects = response.json() if not isinstance(projects, list): return {"status": "error", "message": "No project found for the provided tenant_id"} + if not projects or len(projects) == 0: + return { + "status": "success", + "message": "No projects found, so no need to import" + } data = [ ["project_name", "description","status","company","mongo_project_id"] ] @@ -290,6 +295,17 @@ def import_project(tenant_id, tenant_prefix, access_token,company_name): } task_list = get_task(tenant_id=tenant_id, tenant_prefix=tenant_prefix, access_token=access_token) + # Check if get_task returned an error response + if isinstance(task_list, dict) and "status" in task_list and task_list["status"] == "error": + return {"status": "error", "message": "Failed to fetch tasks", "details": task_list.get("message")} + + # Check if no tasks found (this is not an error, just no data to import) + if not task_list or len(task_list) == 0: + return { + "status": "success", + "message": "No tasks found, so no need to import tasks" + } + task_data = [ ["task_name", "description","assign_to","project","workflow_status","company","mongo_task_id"] ]