{"id":20327446,"url":"https://github.com/eduardogr/evalytics","last_synced_at":"2025-07-07T06:06:11.381Z","repository":{"id":43351176,"uuid":"249792202","full_name":"eduardogr/evalytics","owner":"eduardogr","description":"HR tool to orchestrate the Performance Review Cycle of the employees of a company.","archived":false,"fork":false,"pushed_at":"2025-07-03T09:43:23.000Z","size":543,"stargazers_count":11,"open_issues_count":7,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-03T10:36:14.951Z","etag":null,"topics":["company","evaluation-cycle","evaluation-framework","human-resources","performance-evaluation","python","python-3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eduardogr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-24T18:54:07.000Z","updated_at":"2025-07-03T09:43:27.000Z","dependencies_parsed_at":"2023-10-02T18:52:49.674Z","dependency_job_id":"d1b8ba7a-9bc3-425c-9a8b-056298140422","html_url":"https://github.com/eduardogr/evalytics","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/eduardogr/evalytics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduardogr%2Fevalytics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduardogr%2Fevalytics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduardogr%2Fevalytics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduardogr%2Fevalytics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eduardogr","download_url":"https://codeload.github.com/eduardogr/evalytics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduardogr%2Fevalytics/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264023550,"owners_count":23545688,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["company","evaluation-cycle","evaluation-framework","human-resources","performance-evaluation","python","python-3"],"created_at":"2024-11-14T19:47:39.701Z","updated_at":"2025-07-07T06:06:11.375Z","avatar_url":"https://github.com/eduardogr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e evalytics \u003c/h1\u003e \u003cbr\u003e\n\nThe Evalytics project aim is to be the platform to support a company's Human Resources team within the Performance Evaluation Cycle.\n\n## :bookmark_tabs: Table of Contents\n\n0. [Introduction](#introduction)\n0. [Tech/framework used](#techframework-used)\n0. [Performance Evaluation Cycle](#book-performance-evaluation-cycle)\n0. [API reference](#book-api-reference)\n0. [Setting up Evalytics config](#pencil-setting-up-evalytics-config)\n0. [Hosting Evalytics locally](#computer-hosting-evalytics-locally)\n0. [Google setup for Evalytics](#wrench-google-setup-for-evalytics)\n0. [Contributing](#family-contributing)\n0. [License](#page_with_curl-license)\n\n# Introduction \n![Python Build Status](https://github.com/eduardogr/evalytics/actions/workflows/python-tests.yml/badge.svg?event=push)\n![Docker Build Status](https://github.com/eduardogr/evalytics/actions/workflows/docker-ci.yml/badge.svg?event=push)\n[![Python](https://img.shields.io/badge/Python-v3.9%2B-blue)]()\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/eduardogr/evalytics/blob/master/.github/CONTRIBUTING.md)\n[![GitHub license](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/eduardogr/evalytics/blob/master/.github/LICENSE)  \n\nThis project defines the Performance Evaluation Cycle as a process **_platform-free_**.\n\n**What does _platform-free_ mean?**\n\nIt means that Evalytics is adaptable to the different ecosystems of the different companies depending on the stack of technology they use\n\n\u003e e.g. Google, Microsoft, Slack, own webhooks or services, ... etc \n\nSatisfying heterogeneous requirements and adapting them in a single project where we can choose the technological stack we want to use.\n\n**Is your company's technology stack covered with Evalytics?**\n\nIf your company's technology stack is not satisfied with Evalytics, please, let us know and open a [feature request](https://github.com/eduardogr/evalytics/issues/new?assignees=\u0026labels=\u0026template=feature_request.md).\n\n## Tech/framework used\n\n### Built with\n  - Python 3.9+\n  - [Tornado Web Server](https://www.tornadoweb.org/en/stable/)\n  - [yaml](https://yaml.org/) for app configuration\n  - **docker** for containerization and **docker-compose** for defining and running docker containers\n\n### Integrated with\n  - Google\n    - Google Drive\n    - Google Spreadsheets\n    - Google Docs\n    - Gmail\n  - Slack\n\n## :book: Performance Evaluation Cycle\n\n### Glossary :speech_balloon:\n\n- **Employee**: any person that participate in the process reviewing or being reviewed.\n- **Direct report**: from the manager's perspective, an employee that belongs to a team\n- **Manager**: an employee that leads a group of employees, their direct reports.\n- **Peer**: an employee that co-work with another but with no management relationship.\n- **Survey**: Set of questions to answer. It is related to the area of employees and the relationship of employees.\n- **Eval reports**: Set of responses and data extracted from employee surveys.\n\n### Types of evaluations\n\n- 180º\n    - Employees are going to review theirselves, their manager and their direct reports (if they have it).\n- 360º\n    - 180º evaluation + evaluation of their peers.\n\n### Phases of a Performance Evaluation Cycle\n\n- Peers assignment (just for 360º evaluations)\n    - Here managers are going to decide who is going to review each of their direct reports.\n\n- Review phase\n    - Reviewers gonna review.\n\n- End phase\n    - Gathering surveys' responses and extracting data from them.\n    - Sharing **_eval reports_** with managers\n\n## :book: API reference\n\n### GET /employees\n\nRetrieves the list of employees\n\n```\n\u003e GET /employees HTTP/\u003chttp-version\u003e\n\u003e \n\u003c HTTP/\u003chttp-version\u003e 200 OK\n\u003c Server: TornadoServer/6.0.4\n\u003c Content-Type: application/json; charset=UTF-8\n{\n  \"success\" : true,\n  \"response\" : {\n    \"employees\" : [\n      {\n        \"manager\" : \"employee_1_manager\",\n        \"uid\" : \"employee_1\",\n        \"mail\" : \"employee_1@company.com\",\n        \"area\" : \"area 1\"\n      },\n      ...\n      ...\n      {\n        \"manager\" : \"employee_N_manager\",\n        \"uid\" : \"employee_N\",\n        \"mail\" : \"employee_N@company.com\",\n        \"area\" : \"area 1\"\n      }\n    ]\n  }\n}\n```\n\n### GET /surveys\n\nRetrieves the list of surveys\n\n```\n\u003e GET /surveys HTTP/\u003chttp-version\u003e\n\u003e\n\u003c HTTP/\u003chttp-version\u003e 200 OK\n\u003c Server: TornadoServer/6.0.4\n\u003c Content-Type: application/json; charset=UTF-8\n{\n  \"success\" : true,\n  \"response\" : {\n    \"surveys\" : {\n      \"Area of Employee type 1\" : {\n        \"SELF\" : \"https://survey.url.com/area_type_1/self\",\n        \"PEER_TO_PEER\" : \"https://survey.url.com/area_type_1/peer_peer\",\n        \"MANAGER_PEER\" : \"https://survey.url.com/area_type_1/manager_peer\",\n        \"PEER_MANAGER\" : \"https://survey.url.com/area_type_1/peer_manager\"\n      },\n      ...\n      ...\n      \"Area of Employee type N\" : {\n        \"SELF\" : \"https://survey.url.com/area_type_N/self\",\n        \"PEER_TO_PEER\" : \"https://survey.url.com/area_type_N/peer_peer\",\n        \"MANAGER_PEER\" : \"https://survey.url.com/area_type_N/manager_peer\",\n        \"PEER_MANAGER\" : \"https://survey.url.com/area_type_N/peer_manager\"\n      }\n    }\n  }\n}\n```\n\n### GET /reviewers\n\nRetrieves the list of reviewers\n\n```\n\u003e GET /reviewers HTTP/\u003chttp-version\u003e\n\u003e \n\u003c HTTP/\u003chttp-version\u003e 200 OK\n\u003c Server: TornadoServer/6.0.4\n\u003c Content-Type: application/json; charset=UTF-8\n\n{\n  \"success\" : true,\n  \"response\" : {\n    \"reviewers\" : [\n      {\n        \"employee\" : {\n          \"manager\" : \"employee_1_manager\",\n          \"uid\" : \"employee_1\",\n          \"mail\" : \"employ_1@company.com\",\n          \"area\" : \"area 1\"\n        },\n        \"evals\" : [\n          {\n            \"form\" : \"https://survey.url.com/area_type_1/self\",\n            \"reviewee\" : \"employee_1\",\n            \"kind\" : \"SELF\"\n          },\n          ...\n          ...\n          {\n            \"form\" : \"https://survey.url.com/area_type_1/peer_manager\",\n            \"kind\" : \"PEER_MANAGER\",\n            \"reviewee\" : \"employee_1_manager\"\n          }\n         ]\n      },\n      ...\n      ...\n    ]\n  }\n}\n```\n\n### POST /communications\n\nSends communications\n\n### GET /status\n\nRetrieves the status of the current eval process\n\n```\n\u003e GET /status HTTP/\u003chttp-version\u003e\n\u003e \n\u003c HTTP/\u003chttp-version\u003e 200 OK\n\u003c Server: TornadoServer/6.0.4\n\u003c Content-Type: application/json; charset=UTF-8\n\n{\n  \"success\" : true,\n  \"response\" : {\n    \"status\" : {\n      \"inconsistent\" : {\n        \"employee_1\" : {\n          \"reviewee_X\" : {\n            \"kind\" : \"MANAGER_PEER\",\n            \"reason\" : \"WRONG_REPORTER: 'reviewee_X' is not one of expected reporters. Reporters: [\u003clist of reporters\u003e]\",\n          }\n        }\n      },\n      \"pending\" : [\n        {\n          \"evals\" : [\u003clist of evals\u003e],\n          \"employee\" : {\n            \"uid\" : \"employee_1\",\n            \"area\" : \"area 1\",\n            \"mail\" : \"ruben.mazariegosdelrey@tuenti.com\",\n            \"manager\" : \"aaron\"\n          }\n        },\n      ],\n      \"completed\": {\n        \"employee_X\" : {\n          \"reviewee_A\" : {\n            \"kind\" : \"eval kind\"\n          },\n          ...\n          ...\n          \"reviewee_Z\" : {\n            \"kind\" : \"eval kind\"\n          }\n        },\n        \"employee_Y\" : {\n          \"reviewee_G\" : {\n            \"kind\" : \"eval kind\"\n          },\n          ...\n          ...\n          \"reviewee_R\" : {\n            \"kind\" : \"eval kind\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n### GET /evalreports\n\nRetrieve eval reports\n\n### POST /evalreports\n\nGenerate eval reports\n\n## :pencil: Evalytics Config\n\nThere's an [Evalytics config](./config.yaml.example) to help you configure your Evalytics instance:\n\n* **Eval process**\n\n  - id: Evalytics process ID.\n  - due_date: Evalytics provider for communications delivery. e.g. gmail.\n  - feature_disabling:\n\n* **Providers**\n\n  - storage: Evalytics provider for storage. e.g. google drive.\n  - communication_channel: Evalytics provider for communications delivery. e.g. gmail.\n  - forms_platform: Evalytics provider for surveys. e.g. google forms.\n\n* **Company**\n\n  - domain: domain of your company, e.g. mycompany.com. This will be used for email delivery.\n  - number_of_employees: number of employees in your [orgchart file](./examples/eval-process/0_existing_OrgChart.csv)\n\n* **Gmail provider**\n\n  - mail_subject: Email subject for eval delivery communications.\n  - reminder_mail_subject: Email subject for reminder communications.\n\n* **Google Drive provider**\n\n  - folder: Google Drive folder where files are stored.\n  - org_chart: Google Spreadsheet where employees are listed. [See an example](./examples/eval-process/0_existing_OrgChart.csv).\n  - form_map: Google Spreadsheet where employees forms are listed by kind of form. [See an example](./examples/eval-process/0_existing_FormMap.csv).\n  - form_responses_folder: Google Drive folder where response files are stored.\n  - eval_report_template_id: Google Document ID where we've defined our eval report template. [See an example](./examples/eval-process/0_existing_EvalReportTemplate.md).\n  - eval_report_prefix_name: Prefix for eval reports documents we are going to create.\n      - e.g. if prefix is 'Eval Report: ', files generated for employee1 and employee2 are going to have titles; 'Eval Report: employee1' and 'Eval Report: employee2' \n\nCreate a config.yaml file from [config.yaml.example](./config.yaml.example) with correct values for each key to let Evalytics work properly.\n\n## :computer: Hosting Evalytics locally\n\n### :rocket: Running the Evalytics server\n\nPreparing local environment to run Evalytics:\n\n#### Prerequisites to running it locally\n\n##### Using make + docker-compose\n\nInstall make and docker-compose\n\n##### Using Python virtual envs\n\nFrom the root path of this project:\n\n```\n./scripts/setup.sh\n```\n\n#### Running Evalytics server\n\n##### Using make + docker-compose\n\n```\nmake build\nmake up\n```\n\n##### Using Python virtual envs\n\n```\npython3 server.py\n```\n\n### :rocket: Making requests to the Evalytics server\n\n#### Possible commands\n  - employees\n  - surveys\n  - reviewers\n    \u003e **options**: *--stats*\n  - send_evals\n    \u003e **options**: *--retry*, *--whitelist*\n  - send_due_date_comm\n    \u003e **options**: *--retry*, *--whitelist*\n  - send_reminders\n    \u003e **options**: *--retry*, *--whitelist*\n  - status\n    \u003e **options**: *--inconsistent-files*\n  - reports\n    \u003e **options**: *--dry-run*, *--whitelist*\n\n#### Using make + docker-compose\n\nUsing make target provided\n\n```\nmake request ARGS='\u003ccommand\u003e \u003coptions\u003e'\n```\n\n#### Using Python virtual envs\n\nUsing provided Python client:\n\n```\npython3 client.py \u003ccommnad\u003e \u003coptions\u003e\n```\n\n#### Using cURL directly:\n\n```\ncurl -X HTTP_VERB localhost:8080/\u003cendpoint\u003e | json_pp\n```\n\n## :wrench: Google setup for Evalytics\n\n### Google API credentials\n\n#### Create a Google project :zap:\n\nJust access to [Google APIs](https://console.developers.google.com/).\n\n  - Or [click here](https://console.developers.google.com/projectcreate) for a quick project creation.\n\n#### Create credentials for your project :key:\n\nOnce you have created your project, you can create your project's credentials.\n\nTo manage project's credentials you have the section [api/credentials](https://console.developers.google.com/apis/credentials) within [Google APIs](https://console.developers.google.com/). But if this is your first credentials creation you better follow these steps:\n\n  - First, you have to create the [consent](https://console.developers.google.com/apis/credentials/consent) for your project\n  - Once the consent is already created and you have a name for you google app you can create your credentials:\n      - Go to *+ Create Credentials* and select *OAuth ID client*\n      - Or access to [api/credentials/oauthclient](https://console.developers.google.com/apis/credentials/oauthclient)\n      - The OAuth client type is *other* and choose the name you prefer :smiley:\n\nYou have already created your credentials! :fireworks:\n\nJust place them in a `credentials.json` file in the root of this repository. :heavy_exclamation_mark::heavy_exclamation_mark:\n\n#### Enable Google APIs :books:\n\nYou can see where you have to access for each google api in the doc [google apis usage](doc/google-apis/usage.md)\n\n#### Generating your token.pickle :unlock:\n\nTo authenticate us we have to send a token.pickle to Google APIs, this token.pickle is generated using the file credentials.json.\n\nTo generate this we have the make target google-auth, so, you just have to tun\n\n  - `make google-auth`\n\n\n:warning: Credentials files to authenticate yourself are included in our [.gitignore](.gitignore)\n\n:angel: So, you don't have to worry about that :smiley:\n\n### Evalytics google files examples\n\n```\nexamples/\n        eval-process/: Example documents for each eval subprocess\n        google-api-client/: Example clients for each google api that we use\n```\n\n## :family: Contributing\n\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/eduardogr/evalytics/blob/master/.github/CONTRIBUTING.md)\n\nContributions are welcome! Please see our [Contributing Guide](\u003chttps://github.com/eduardogr/evalytics/blob/master/.github/CONTRIBUTING.md\u003e) for more\ndetails.\n\n## :page_with_curl: License\n\nThis project is licensed under the [Apache license](https://github.com/eduardogr/evalytics/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduardogr%2Fevalytics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feduardogr%2Fevalytics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduardogr%2Fevalytics/lists"}