Repository: it-projects-llc/misc-addons Branch: 14.0 Commit: a605936278fc Files: 44 Total size: 109.5 KB Directory structure: gitextract_cvrop6my/ ├── .copier-answers.yml ├── .editorconfig ├── .eslintrc.yml ├── .flake8 ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── pre-commit.yml │ └── test.yml ├── .gitignore ├── .isort.cfg ├── .oca_hooks.cfg ├── .pre-commit-config.yaml ├── .prettierrc.yml ├── .pylintrc ├── .pylintrc-mandatory ├── LICENSE ├── README.md ├── project_task_subtask/ │ ├── README.rst │ ├── __init__.py │ ├── __manifest__.py │ ├── data/ │ │ └── subscription_template.xml │ ├── demo/ │ │ └── project_task_subtask_demo.xml │ ├── i18n/ │ │ ├── es_CR.po │ │ ├── fr.po │ │ ├── project_task_subtask.pot │ │ ├── ru.po │ │ └── sl.po │ ├── models/ │ │ ├── __init__.py │ │ └── project_task_subtask.py │ ├── readme/ │ │ ├── CONTRIBUTORS.md │ │ ├── DESCRIPTION.md │ │ └── USAGE.md │ ├── security/ │ │ └── ir.model.access.csv │ ├── static/ │ │ ├── description/ │ │ │ └── index.html │ │ └── src/ │ │ ├── css/ │ │ │ └── kanban_styles.css │ │ ├── js/ │ │ │ ├── one2many_renderer.js │ │ │ └── tours/ │ │ │ └── tour.js │ │ └── xml/ │ │ └── templates.xml │ ├── tests/ │ │ ├── __init__.py │ │ └── test_subtask_sort_button.py │ └── views/ │ ├── assets.xml │ └── project_task_subtask.xml └── setup/ ├── .setuptools-odoo-make-default-ignore ├── README └── project_task_subtask/ └── setup.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .copier-answers.yml ================================================ # Do NOT update manually; changes here will be overwritten by Copier _commit: 089da8d _src_path: https://github.com/it-projects-llc/oca-addons-repo-template ci: GitHub convert_readme_fragments_to_markdown: false generate_requirements_txt: true github_check_license: true github_ci_extra_env: {} github_enable_codecov: true github_enable_makepot: false github_enable_stale_action: false github_enforce_dev_status_compatibility: false include_wkhtmltopdf: false odoo_test_flavor: Both odoo_version: 14.0 org_name: IT-Projects LLC org_slug: it-projects-llc rebel_module_groups: [] repo_description: '' repo_name: '' repo_slug: misc-addons repo_website: https://github.com/it-projects-llc/misc-addons use_pyproject_toml: false use_ruff: false ================================================ FILE: .editorconfig ================================================ # Configuration for known file extensions [*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] charset = utf-8 end_of_line = lf indent_size = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true [*.{json,yml,yaml,rst,md}] indent_size = 2 # Do not configure editor for libs and autogenerated content [{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] charset = unset end_of_line = unset indent_size = unset indent_style = unset insert_final_newline = false trim_trailing_whitespace = false ================================================ FILE: .eslintrc.yml ================================================ env: browser: true es6: true # See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 parserOptions: ecmaVersion: 2019 overrides: - files: - "**/*.esm.js" parserOptions: sourceType: module # Globals available in Odoo that shouldn't produce errorings globals: _: readonly $: readonly fuzzy: readonly jQuery: readonly moment: readonly odoo: readonly openerp: readonly owl: readonly luxon: readonly # Styling is handled by Prettier, so we only need to enable AST rules; # see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 rules: accessor-pairs: warn array-callback-return: warn callback-return: warn capitalized-comments: - warn - always - ignoreConsecutiveComments: true ignoreInlineComments: true complexity: - warn - 15 constructor-super: warn dot-notation: warn eqeqeq: warn global-require: warn handle-callback-err: warn id-blacklist: warn id-match: warn init-declarations: error max-depth: warn max-nested-callbacks: warn max-statements-per-line: warn no-alert: warn no-array-constructor: warn no-caller: warn no-case-declarations: warn no-class-assign: warn no-cond-assign: error no-const-assign: error no-constant-condition: warn no-control-regex: warn no-debugger: error no-delete-var: warn no-div-regex: warn no-dupe-args: error no-dupe-class-members: error no-dupe-keys: error no-duplicate-case: error no-duplicate-imports: error no-else-return: warn no-empty-character-class: warn no-empty-function: error no-empty-pattern: error no-empty: warn no-eq-null: error no-eval: error no-ex-assign: error no-extend-native: warn no-extra-bind: warn no-extra-boolean-cast: warn no-extra-label: warn no-fallthrough: warn no-func-assign: error no-global-assign: error no-implicit-coercion: - warn - allow: ["~"] no-implicit-globals: warn no-implied-eval: warn no-inline-comments: warn no-inner-declarations: warn no-invalid-regexp: warn no-irregular-whitespace: warn no-iterator: warn no-label-var: warn no-labels: warn no-lone-blocks: warn no-lonely-if: error no-mixed-requires: error no-multi-str: warn no-native-reassign: error no-negated-condition: warn no-negated-in-lhs: error no-new-func: warn no-new-object: warn no-new-require: warn no-new-symbol: warn no-new-wrappers: warn no-new: warn no-obj-calls: warn no-octal-escape: warn no-octal: warn no-param-reassign: warn no-path-concat: warn no-process-env: warn no-process-exit: warn no-proto: warn no-prototype-builtins: warn no-redeclare: warn no-regex-spaces: warn no-restricted-globals: warn no-restricted-imports: warn no-restricted-modules: warn no-restricted-syntax: warn no-return-assign: error no-script-url: warn no-self-assign: warn no-self-compare: warn no-sequences: warn no-shadow-restricted-names: warn no-shadow: warn no-sparse-arrays: warn no-sync: warn no-this-before-super: warn no-throw-literal: warn no-undef-init: warn no-undef: error no-unmodified-loop-condition: warn no-unneeded-ternary: error no-unreachable: error no-unsafe-finally: error no-unused-expressions: error no-unused-labels: error no-unused-vars: warn no-use-before-define: error no-useless-call: warn no-useless-computed-key: warn no-useless-concat: warn no-useless-constructor: warn no-useless-escape: warn no-useless-rename: warn no-void: warn no-with: warn operator-assignment: [error, always] prefer-const: warn radix: warn require-yield: warn sort-imports: warn spaced-comment: [error, always] strict: [error, function] use-isnan: error valid-jsdoc: - warn - prefer: arg: param argument: param augments: extends constructor: class exception: throws func: function method: function prop: property return: returns virtual: abstract yield: yields preferType: array: Array bool: Boolean boolean: Boolean number: Number object: Object str: String string: String requireParamDescription: false requireReturn: false requireReturnDescription: false requireReturnType: false valid-typeof: warn yoda: warn ================================================ FILE: .flake8 ================================================ [flake8] max-line-length = 88 max-complexity = 16 # B = bugbear # B9 = bugbear opinionated (incl line length) select = C,E,F,W,B,B9 # E203: whitespace before ':' (black behaviour) # E501: flake8 line length (covered by bugbear B950) # W503: line break before binary operator (black behaviour) ignore = E203,E501,W503 per-file-ignores= __init__.py:F401 ================================================ FILE: .github/FUNDING.yml ================================================ custom: "https://www.paypal.me/ITProPayment" ================================================ FILE: .github/workflows/pre-commit.yml ================================================ name: pre-commit on: pull_request: branches: - "14.0*" push: branches: - "14.0" - "14.0-ocabot-*" jobs: pre-commit: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v2 with: python-version: "3.11" - name: Get python version run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - uses: actions/cache@v1 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} - name: Install pre-commit run: pip install pre-commit - name: Run pre-commit run: pre-commit run --all-files --show-diff-on-failure --color=always env: # Consider valid a PR that changes README fragments but doesn't # change the README.rst file itself. It's not really a problem # because the bot will update it anyway after merge. This way, we # lower the barrier for functional contributors that want to fix the # readme fragments, while still letting developers get README # auto-generated (which also helps functionals when using runboat). # DOCS https://pre-commit.com/#temporarily-disabling-hooks SKIP: oca-gen-addon-readme - name: Check that all files generated by pre-commit are in git run: | newfiles="$(git ls-files --others --exclude-from=.gitignore)" if [ "$newfiles" != "" ] ; then echo "Please check-in the following files:" echo "$newfiles" exit 1 fi ================================================ FILE: .github/workflows/test.yml ================================================ name: tests on: pull_request: branches: - "14.0*" push: branches: - "14.0" - "14.0-ocabot-*" jobs: unreleased-deps: runs-on: ubuntu-latest name: Detect unreleased dependencies steps: - uses: actions/checkout@v3 - run: | for reqfile in requirements.txt test-requirements.txt ; do if [ -f ${reqfile} ] ; then result=0 # reject non-comment lines that contain a / (i.e. URLs, relative paths) grep "^[^#].*/" ${reqfile} || result=$? if [ $result -eq 0 ] ; then echo "Unreleased dependencies found in ${reqfile}." exit 1 fi fi done test: runs-on: ubuntu-22.04 container: ${{ matrix.container }} name: ${{ matrix.name }} strategy: fail-fast: false matrix: include: - container: ghcr.io/oca/oca-ci/py3.6-odoo14.0:latest name: test with Odoo - container: ghcr.io/oca/oca-ci/py3.6-ocb14.0:latest name: test with OCB makepot: "false" services: postgres: image: postgres:9.6 env: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo POSTGRES_DB: odoo ports: - 5432:5432 steps: - uses: actions/checkout@v3 with: persist-credentials: false - name: Install addons and dependencies run: oca_install_addons - name: Check licenses run: manifestoo -d . check-licenses - name: Check development status run: manifestoo -d . check-dev-status --default-dev-status=Beta continue-on-error: true - name: Initialize test db run: oca_init_test_database - name: Run tests run: oca_run_tests - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} - name: Update .pot files run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'it-projects-llc' }} ================================================ FILE: .gitignore ================================================ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] /.venv /.pytest_cache /.ruff_cache # C extensions *.so # Distribution / packaging .Python env/ bin/ build/ develop-eggs/ dist/ eggs/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg *.eggs # Windows installers *.msi # Debian packages *.deb # Redhat packages *.rpm # MacOS packages *.dmg *.pkg # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo # Pycharm .idea # Eclipse .settings # Visual Studio cache/options directory .vs/ .vscode # OSX Files .DS_Store # Django stuff: *.log # Mr Developer .mr.developer.cfg .project .pydevproject # Rope .ropeproject # Sphinx documentation docs/_build/ # Backup files *~ *.swp # OCA rules !static/lib/ ================================================ FILE: .isort.cfg ================================================ [settings] ; see https://github.com/psf/black multi_line_output=3 include_trailing_comma=True force_grid_wrap=0 combine_as_imports=True use_parentheses=True line_length=88 known_odoo=odoo known_odoo_addons=odoo.addons sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER default_section=THIRDPARTY ensure_newline_before_comments = True ================================================ FILE: .oca_hooks.cfg ================================================ [MESSAGES_CONTROL] disable=xml-deprecated-data-node,xml-deprecated-tree-attribute ================================================ FILE: .pre-commit-config.yaml ================================================ exclude: | (?x) # NOT INSTALLABLE ADDONS # END NOT INSTALLABLE ADDONS # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| # We don't want to mess with tool-generated files .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| # Maybe reactivate this when all README files include prettier ignore tags? ^README\.md$| # Library files can have extraneous formatting (even minimized) /static/(src/)?lib/| # Repos using Sphinx to generate docs don't need prettying ^docs/_templates/.*\.html$| # Don't bother non-technical authors with formatting issues in docs readme/.*\.(rst|md)$| # Ignore build and dist directories in addons /build/|/dist/| # Ignore test files in addons /tests/samples/.*| # You don't usually want a bot to modify your legal texts (LICENSE.*|COPYING.*) default_language_version: python: python3 node: "14.13.0" repos: - repo: local hooks: # These files are most likely copier diff rejection junks; if found, # review them manually, fix the problem (if needed) and remove them - id: forbidden-files name: forbidden files entry: found forbidden files; remove them language: fail files: "\\.rej$" - id: en-po-files name: en.po files cannot exist entry: found a en.po file language: fail files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools rev: d5fab7ee87fceee858a3d01048c78a548974d935 hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons - id: oca-fix-manifest-website args: ["https://github.com/it-projects-llc/misc-addons"] - id: oca-gen-addon-readme args: - --addons-dir=. - --branch=14.0 - --org-name=it-projects-llc - --repo-name=misc-addons - --if-source-changed - --keep-source-digest - repo: https://github.com/OCA/odoo-pre-commit-hooks rev: v0.0.25 hooks: - id: oca-checks-odoo-module - id: oca-checks-po - repo: https://github.com/myint/autoflake rev: v1.4 hooks: - id: autoflake args: - --expand-star-imports - --ignore-init-module-imports - --in-place - --remove-all-unused-imports - --remove-duplicate-keys - --remove-unused-variables - repo: https://github.com/psf/black rev: 22.3.0 hooks: - id: black - repo: https://github.com/pre-commit/mirrors-prettier rev: v2.1.2 hooks: - id: prettier name: prettier (with plugin-xml) additional_dependencies: - "prettier@2.1.2" - "@prettier/plugin-xml@0.12.0" args: - --plugin=@prettier/plugin-xml files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ - repo: https://github.com/pre-commit/mirrors-eslint rev: v7.8.1 hooks: - id: eslint verbose: true args: - --color - --fix - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.2.0 hooks: - id: trailing-whitespace # exclude autogenerated files exclude: /README\.rst$|\.pot?$ - id: end-of-file-fixer # exclude autogenerated files exclude: /README\.rst$|\.pot?$ - id: debug-statements - id: fix-encoding-pragma args: ["--remove"] - id: check-case-conflict - id: check-docstring-first - id: check-executables-have-shebangs - id: check-merge-conflict # exclude files where underlines are not distinguishable from merge conflicts exclude: /README\.rst$|^docs/.*\.rst$ - id: check-symlinks - id: check-xml - id: mixed-line-ending args: ["--fix=lf"] - repo: https://github.com/asottile/pyupgrade rev: v2.7.2 hooks: - id: pyupgrade args: ["--keep-percent-format"] - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: - id: isort name: isort except __init__.py args: - --settings=. exclude: /__init__\.py$ - repo: https://github.com/acsone/setuptools-odoo rev: 3.1.8 hooks: - id: setuptools-odoo-make-default - id: setuptools-odoo-get-requirements args: - --output - requirements.txt - --header - "# generated from manifests external_dependencies" - repo: https://github.com/PyCQA/flake8 rev: 3.8.3 hooks: - id: flake8 name: flake8 additional_dependencies: ["flake8-bugbear==20.1.4"] - repo: https://github.com/OCA/pylint-odoo rev: 7.0.2 hooks: - id: pylint_odoo name: pylint with optional checks args: - --rcfile=.pylintrc - --exit-zero verbose: true - id: pylint_odoo args: - --rcfile=.pylintrc-mandatory ================================================ FILE: .prettierrc.yml ================================================ # Defaults for all prettier-supported languages. # Prettier will complete this with settings from .editorconfig file. bracketSpacing: false printWidth: 88 proseWrap: always semi: true trailingComma: "es5" xmlWhitespaceSensitivity: "strict" ================================================ FILE: .pylintrc ================================================ [MASTER] load-plugins=pylint_odoo score=n [ODOOLINT] readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" manifest_required_authors=IT-Projects LLC manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 valid_odoo_versions=14.0 [MESSAGES CONTROL] disable=all # This .pylintrc contains optional AND mandatory checks and is meant to be # loaded in an IDE to have it check everything, in the hope this will make # optional checks more visible to contributors who otherwise never look at a # green travis to see optional checks that failed. # .pylintrc-mandatory containing only mandatory checks is used the pre-commit # config as a blocking check. enable=anomalous-backslash-in-string, api-one-deprecated, api-one-multi-together, assignment-from-none, attribute-deprecated, class-camelcase, dangerous-default-value, dangerous-view-replace-wo-priority, development-status-allowed, duplicate-id-csv, duplicate-key, duplicate-xml-fields, duplicate-xml-record-id, eval-referenced, eval-used, incoherent-interpreter-exec-perm, license-allowed, manifest-author-string, manifest-deprecated-key, manifest-required-author, manifest-required-key, manifest-version-format, method-compute, method-inverse, method-required-super, method-search, openerp-exception-warning, pointless-statement, pointless-string-statement, print-used, redundant-keyword-arg, redundant-modulename-xml, reimported, relative-import, return-in-init, rst-syntax-error, sql-injection, too-few-format-args, translation-field, translation-required, unreachable, use-vim-comment, wrong-tabs-instead-of-spaces, xml-syntax-error, # messages that do not cause the lint step to fail consider-merging-classes-inherited, create-user-wo-reset-password, dangerous-filter-wo-user, deprecated-module, file-not-used, invalid-commit, missing-manifest-dependency, missing-newline-extrafiles, missing-readme, no-utf8-coding-comment, odoo-addons-relative-import, old-api7-method-defined, redefined-builtin, too-complex, unnecessary-utf8-coding-comment [REPORTS] msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} output-format=colorized reports=no ================================================ FILE: .pylintrc-mandatory ================================================ [MASTER] load-plugins=pylint_odoo score=n [ODOOLINT] readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" manifest_required_authors=IT-Projects LLC manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 valid_odoo_versions=14.0 [MESSAGES CONTROL] disable=all enable=anomalous-backslash-in-string, api-one-deprecated, api-one-multi-together, assignment-from-none, attribute-deprecated, class-camelcase, dangerous-default-value, dangerous-view-replace-wo-priority, development-status-allowed, duplicate-id-csv, duplicate-key, duplicate-xml-fields, duplicate-xml-record-id, eval-referenced, eval-used, incoherent-interpreter-exec-perm, license-allowed, manifest-author-string, manifest-deprecated-key, manifest-required-author, manifest-required-key, manifest-version-format, method-compute, method-inverse, method-required-super, method-search, openerp-exception-warning, pointless-statement, pointless-string-statement, print-used, redundant-keyword-arg, redundant-modulename-xml, reimported, relative-import, return-in-init, rst-syntax-error, sql-injection, too-few-format-args, translation-field, translation-required, unreachable, use-vim-comment, wrong-tabs-instead-of-spaces, xml-syntax-error [REPORTS] msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} output-format=colorized reports=no ================================================ FILE: LICENSE ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: README.md ================================================ [![Pre-commit Status](https://github.com/it-projects-llc/misc-addons/actions/workflows/pre-commit.yml/badge.svg?branch=14.0)](https://github.com/it-projects-llc/misc-addons/actions/workflows/pre-commit.yml?query=branch%3A14.0) [![Build Status](https://github.com/it-projects-llc/misc-addons/actions/workflows/test.yml/badge.svg?branch=14.0)](https://github.com/it-projects-llc/misc-addons/actions/workflows/test.yml?query=branch%3A14.0) [![codecov](https://codecov.io/gh/it-projects-llc/misc-addons/branch/14.0/graph/badge.svg)](https://codecov.io/gh/it-projects-llc/misc-addons) # [//]: # (addons) This part will be replaced when running the oca-gen-addons-table script from OCA/maintainer-tools. [//]: # (end addons) ## Licenses This repository is licensed under [LGPL-3.0](LICENSE). However, each module can have a totally different license, as long as they adhere to IT-Projects LLC policy. Consult each module's `__manifest__.py` file, which contains a `license` key that explains its license. ---- ================================================ FILE: project_task_subtask/README.rst ================================================ ====================== Project Task Checklist ====================== .. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:3a3f0575b71186dece7826cf32d1bfc8cbfa7c3076d64352bcca8a09c4fd41a9 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta .. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-it--projects--llc%2Fmisc--addons-lightgray.png?logo=github :target: https://github.com/it-projects-llc/misc-addons/tree/14.0/project_task_subtask :alt: it-projects-llc/misc-addons |badge1| |badge2| |badge3| Use subtasks to control your tasks. Be ensure that all your tasks/subtasks are performed and not missed. Features: - Added new "Checklist" tab on task's form - When new subtask is created\\changed, message is sent to user that assigned to this subtask - Only users related to subtask can change subtask parameters - All subtasks have a certain color, informing about their state - Each subtask has buttons to switch state: - DONE - TODO - CANCELLED - Added new "Checklist" menu - default filter: "My", "TODO" - optional group by: "Project", "Task", "User", "State" **Table of contents** .. contents:: :local: Usage ===== - Create User1 and User2 in the ``Settings >> Users`` menu - Login as User1 - Go to ``Project >> Project >> All Tasks`` and open the ``Checklist`` tab - Create new subtask (Assigned to - User2) - Login as User2 - See message in Inbox like "TODO: subtask_name" - Change state of subtask to Cancelled/Done - You can see a message in Inbox "Cancelled: subtask_name" or "Done: subtask_name" accordingly. - You can see your TODOs on tasks in kanban view in the ``Project >> Project >> Tasks`` menu - The ``Project >> Project >> Checklist`` menu displays ALL subtasks in state TODO assigned to you and subtasks where you are Reviewer Bug Tracker =========== Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed `feedback `_. Do not contact contributors directly about support or help with technical issues. Credits ======= Authors ------- * IT-Projects LLC Contributors ------------ - Ivan Yelizariev (https://github.com/yelizariev) - Rafael Manaev (https://github.com/manawi) - Ilmir Karamov (https://github.com/ilmir-k) - Ildar Nasyrov (https://github.com/iledarn) - Nicolas Jeudy (https://github.com/njeudy) - Alexandr Kolushov (https://github.com/KolushovAlexandr) - Almas Giniatullin (https://github.com/almas50) - Denis Mudarisov (https://github.com/trojikman) - Vildan Safin (https://github.com/Enigma228322) - Eugene Molotov (https://github.com/em230418) - Victor Bykov (https://github.com/BykovVik) Maintainers ----------- This module is part of the `it-projects-llc/misc-addons `_ project on GitHub. You are welcome to contribute. ================================================ FILE: project_task_subtask/__init__.py ================================================ # License MIT (https://opensource.org/licenses/MIT). from . import models ================================================ FILE: project_task_subtask/__manifest__.py ================================================ { "name": """Project Task Checklist""", "summary": """Use checklist to be ensure that all your tasks are performed and to make easy control over them""", # noqa: B950 "category": """Project Management""", "images": ["images/checklist_main.png"], "version": "14.0.1.1.2", "author": "IT-Projects LLC", "support": "it@it-projects.info", "website": "https://github.com/it-projects-llc/misc-addons", "license": "LGPL-3", "depends": ["project"], "data": [ "security/ir.model.access.csv", "views/project_task_subtask.xml", "views/assets.xml", "data/subscription_template.xml", ], "qweb": ["static/src/xml/templates.xml"], "demo": ["demo/project_task_subtask_demo.xml"], } ================================================ FILE: project_task_subtask/data/subscription_template.xml ================================================ All checklist updates project.task Subscribe to checklist updates of other users. By default you are notified on checklist items to and from you only. All checklist updates Subscribe to checklist updates of other users. By default you are notified on checklist items to and from you only. 10 project.project project_id ================================================ FILE: project_task_subtask/demo/project_task_subtask_demo.xml ================================================ test subtask ================================================ FILE: project_task_subtask/i18n/es_CR.po ================================================ # Translation of Odoo Server. # This file contains the translation of the following modules: # * project_task_subtask # # Translators: # Randall , 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-30 21:57+0000\n" "PO-Revision-Date: 2018-04-30 21:57+0000\n" "Last-Translator: Randall , 2018\n" "Language-Team: Spanish (Costa Rica) (https://www.transifex.com/it-projects-llc/teams/76080/es_CR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: es_CR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: project_task_subtask #: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype msgid "All checklist updates" msgstr "Todas las actualizaciones de la lista de verificación" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id msgid "Assigned to" msgstr "Asignado a" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Cancelled" msgstr "Cancelado" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to CANCELLED" msgstr "Cambiar estado a CANCELADO" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to DONE" msgstr "Cambiar estado a TERMINADO" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to TODO" msgstr "Cambiar estado a POR HACER" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to WAITING" msgstr "Cambiar estado a ESPERANDO" #. module: project_task_subtask #: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask #: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Checklist" msgstr "Lista de Verificación" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid msgid "Created by" msgstr "Creado por" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date msgid "Created on" msgstr "Creado en" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline msgid "Deadline" msgstr "Tiempo Entrega" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user msgid "Default User" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Description" msgstr "Descripción" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name msgid "Display Name" msgstr "Mostrar Nombre" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Done" msgstr "Terminado" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Filter" msgstr "Filtro" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Group By" msgstr "Agrupar por" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button msgid "Hide Button" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id msgid "ID" msgstr "ID" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks msgid "Kanban Subtasks" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update msgid "Last Modified on" msgstr "Última Modificación el" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid msgid "Last Updated by" msgstr "Última Modificación por" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date msgid "Last Updated on" msgstr "Última Actualización en" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "My" msgstr "Mi" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:60 #: code:addons/project_task_subtask/models/project_task_subtask.py:64 #, python-format msgid "Only users related to that subtask can change state." msgstr "" "Sólo los usuarios relacionados a la sub tarea pueden cambiarla de estado" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id_2779 #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Project" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor msgid "Recolor" msgstr "Cambiar Color" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id msgid "Reviewer" msgstr "Revisado Por" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "State" msgstr "Estado" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state msgid "Status" msgstr "Estatus" #. module: project_task_subtask #: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype msgid "" "Subscribe to checklist updates of other users. By default you are notified " "on checklist items to and from you only." msgstr "" "Suscríbete a las actualizaciones de la lista de verificación de otros " "usuarios. De forma predeterminada, se le notifica solo en los elementos de " "la lista de verificación." #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids msgid "Subtask" msgstr "Sub tarea" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_id msgid "Subtask Message" msgstr "Mensaje Sub tarea" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search #: selection:project.task.subtask,state:0 msgid "TODO" msgstr "Por Hacer" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Task" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state msgid "Task state" msgstr "Estado tarea" #. module: project_task_subtask #: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 msgid "To Do" msgstr "Por Hacer" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "User" msgstr "Usuario" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Waiting" msgstr "Esperando" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task_subtask msgid "project.task.subtask" msgstr "project.task.subtask" ================================================ FILE: project_task_subtask/i18n/fr.po ================================================ # Translation of Odoo Server. # This file contains the translation of the following modules: # * project_task_subtask # # Translators: # Translation Bot , 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-04-20 23:52+0000\n" "PO-Revision-Date: 2018-04-20 23:52+0000\n" "Last-Translator: Translation Bot , 2018\n" "Language-Team: French (https://www.transifex.com/it-projects-llc/teams/76080/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. module: project_task_subtask #: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype msgid "All checklist updates" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id msgid "Assigned to" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Cancelled" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to CANCELLED" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to DONE" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to TODO" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to WAITING" msgstr "" #. module: project_task_subtask #: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask #: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Checklist" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid msgid "Created by" msgstr "Créé par" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date msgid "Created on" msgstr "Créé le" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline msgid "Deadline" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user msgid "Default user" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Description" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name msgid "Display Name" msgstr "Nom affiché" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Done" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Filter" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Group By" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button msgid "Hide button" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id msgid "ID" msgstr "ID" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks msgid "Kanban subtasks" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update msgid "Last Modified on" msgstr "Dernière Modification le" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid msgid "Last Updated by" msgstr "Dernière mise à jour par" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date msgid "Last Updated on" msgstr "Dernière mise à jour le" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "My" msgstr "" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:61 #: code:addons/project_task_subtask/models/project_task_subtask.py:65 #, python-format msgid "Only users related to that subtask can change state." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Project" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor msgid "Recolor" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id msgid "Reviewer" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "State" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state msgid "Status" msgstr "" #. module: project_task_subtask #: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype msgid "" "Subscribe to checklist updates of other users. By default you are notified " "on checklist items to and from you only." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids msgid "Subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_id msgid "Subtask Message" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search #: selection:project.task.subtask,state:0 msgid "TODO" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Task" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Task Work" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state msgid "Task state" msgstr "" #. module: project_task_subtask #: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 msgid "To Do" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "User" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Waiting" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task_subtask msgid "project.task.subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view msgid "subtask_list_form" msgstr "" ================================================ FILE: project_task_subtask/i18n/project_task_subtask.pot ================================================ # Translation of Odoo Server. # This file contains the translation of the following modules: # * project_task_subtask # msgid "" msgstr "" "Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" #. module: project_task_subtask #: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype msgid "All checklist updates" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id msgid "Assigned to" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Cancelled" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to CANCELLED" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to DONE" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to TODO" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to Waiting" msgstr "" #. module: project_task_subtask #: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask #: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Checklist" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_completion msgid "Completion" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_completion_xml msgid "Completion Xml" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id msgid "Created by" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date msgid "Created on" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline msgid "Deadline" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user msgid "Default User" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Description" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name msgid "Display Name" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Done" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Filter" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Group By" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button msgid "Hide Button" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id msgid "ID" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks msgid "Kanban Subtasks" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update msgid "Last Modified on" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid msgid "Last Updated by" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date msgid "Last Updated on" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "My" msgstr "" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:67 #: code:addons/project_task_subtask/models/project_task_subtask.py:71 #, python-format msgid "Only users related to that subtask can change state." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id_4692 #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Project" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor msgid "Recolor" msgstr "" #. module: project_task_subtask #. openerp-web #: code:addons/project_task_subtask/static/src/xml/templates.xml:6 #, python-format msgid "Sort" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "State" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state msgid "Status" msgstr "" #. module: project_task_subtask #: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype msgid "Subscribe to checklist updates of other users. By default you are notified on checklist items to and from you only." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids msgid "Subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_id msgid "Subtask Message" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search #: selection:project.task.subtask,state:0 msgid "TODO" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Task" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state msgid "Task state" msgstr "" #. module: project_task_subtask #: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 msgid "To Do" msgstr "" #. module: project_task_subtask #. openerp-web #: code:addons/project_task_subtask/static/src/xml/templates.xml:7 #, python-format msgid "Unsort" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "User" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Waiting" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task_subtask msgid "project.task.subtask" msgstr "" ================================================ FILE: project_task_subtask/i18n/ru.po ================================================ # Translation of Odoo Server. # This file contains the translation of the following modules: # * project_task_subtask # # Translators: # Dinar , 2017 msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-11-22 11:27+0000\n" "PO-Revision-Date: 2017-11-22 11:27+0000\n" "Last-Translator: Dinar , 2017\n" "Language-Team: Russian (https://www.transifex.com/it-projects-llc/teams/76080/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" #. module: project_task_subtask #: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype msgid "All checklist updates" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id msgid "Assigned to" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Cancelled" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to CANCELLED" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to DONE" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to TODO" msgstr "" #. module: project_task_subtask #: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask #: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Checklist" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid msgid "Created by" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date msgid "Created on" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user msgid "Default user" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name msgid "Description" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name msgid "Display Name" msgstr "Отображаемое имя" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Done" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Filter" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Group By" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button msgid "Hide button" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id msgid "ID" msgstr "ID" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks msgid "Kanban subtasks" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update msgid "Last Modified on" msgstr "Последний раз редактировалось" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid msgid "Last Updated by" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date msgid "Last Updated on" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "My" msgstr "" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:60 #: code:addons/project_task_subtask/models/project_task_subtask.py:64 #, python-format msgid "Only users related to that subtask can change state." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Project" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor msgid "Recolor" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id msgid "Reviewer" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "State" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state msgid "Status" msgstr "" #. module: project_task_subtask #: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype msgid "" "Subscribe to checklist updates of other users. By default you are notified " "on checklist items to and from you only." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids msgid "Subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_id msgid "Subtask Message" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search #: selection:project.task.subtask,state:0 msgid "TODO" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Task" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Task Work" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state msgid "Task state" msgstr "" #. module: project_task_subtask #: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 msgid "To Do" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "User" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Waiting" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task_subtask msgid "project.task.subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view msgid "subtask_list_form" msgstr "" ================================================ FILE: project_task_subtask/i18n/sl.po ================================================ # Translation of Odoo Server. # This file contains the translation of the following modules: # * project_task_subtask # # Translators: # Translation Bot , 2017 msgid "" msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-24 07:50+0000\n" "PO-Revision-Date: 2017-07-24 07:50+0000\n" "Last-Translator: Translation Bot , 2017\n" "Language-Team: Slovenian (https://www.transifex.com/it-projects-llc/teams/76080/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Language: sl\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" #. module: project_task_subtask #: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype msgid "All checklist updates" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id msgid "Assigned to" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Cancelled" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to CANCELLED" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to DONE" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Change state to TODO" msgstr "" #. module: project_task_subtask #: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask #: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Checklist" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid msgid "Created by" msgstr "Ustvaril" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date msgid "Created on" msgstr "Ustvarjeno" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user msgid "Default user" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name msgid "Description" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name msgid "Display Name" msgstr "" #. module: project_task_subtask #: selection:project.task.subtask,state:0 msgid "Done" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Filter" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Group By" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button msgid "Hide button" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id msgid "ID" msgstr "ID" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks msgid "Kanban subtasks" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update msgid "Last Modified on" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid msgid "Last Updated by" msgstr "Zadnjič posodobil" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date msgid "Last Updated on" msgstr "Zadnjič posodobljeno" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "My" msgstr "" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:62 #, python-format msgid "Only reviewer can change description." msgstr "" #. module: project_task_subtask #: code:addons/project_task_subtask/models/project_task_subtask.py:58 #, python-format msgid "Only users related to that subtask can change state." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Project" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor msgid "Recolor" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id msgid "Reviewer" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "State" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state msgid "Status" msgstr "" #. module: project_task_subtask #: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype #: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype msgid "" "Subscribe to checklist updates of other users. By default you are notified " "on checklist items to and from you only." msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids msgid "Subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_id msgid "Subtask Message" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search #: selection:project.task.subtask,state:0 msgid "TODO" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "Task" msgstr "Opravilo" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 msgid "Task Work" msgstr "" #. module: project_task_subtask #: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state msgid "Task state" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search msgid "User" msgstr "" #. module: project_task_subtask #: model:ir.model,name:project_task_subtask.model_project_task_subtask msgid "project.task.subtask" msgstr "" #. module: project_task_subtask #: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view msgid "subtask_list_form" msgstr "" ================================================ FILE: project_task_subtask/models/__init__.py ================================================ from . import project_task_subtask ================================================ FILE: project_task_subtask/models/project_task_subtask.py ================================================ from odoo import api, fields, models from odoo.exceptions import Warning as UserError from odoo.tools import html_escape as escape from odoo.tools.translate import _ SUBTASK_STATES = { "done": "Done", "todo": "TODO", "waiting": "Waiting", "cancelled": "Cancelled", } class ProjectTaskSubtask(models.Model): _name = "project.task.subtask" _description = "Subtask" _inherit = ["mail.activity.mixin"] state = fields.Selection( [(k, v) for k, v in list(SUBTASK_STATES.items())], "Status", required=True, copy=False, default="todo", ) name = fields.Char(required=True, string="Description") reviewer_id = fields.Many2one( "res.users", "Reviewer", readonly=True, default=lambda self: self.env.user ) project_id = fields.Many2one( "project.project", related="task_id.project_id", store=True ) user_id = fields.Many2one("res.users", "Assigned to", required=True) task_id = fields.Many2one( "project.task", "Task", ondelete="cascade", required=True, index="1" ) task_state = fields.Char( string="Task state", related="task_id.stage_id.name", readonly=True ) hide_button = fields.Boolean(compute="_compute_hide_button") recolor = fields.Boolean(compute="_compute_recolor") deadline = fields.Datetime(string="Deadline") def _compute_recolor(self): for record in self: if self.env.user == record.user_id and record.state == "todo": record.recolor = True else: record.recolor = False def _compute_hide_button(self): for record in self: if self.env.user not in [record.reviewer_id, record.user_id]: record.hide_button = True else: record.hide_button = False def _compute_reviewer_id(self): for record in self: record.reviewer_id = record.create_uid @api.model def _needaction_domain_get(self): if self._needaction: return [("state", "=", "todo"), ("user_id", "=", self.env.uid)] return [] def write(self, vals): old_names = dict(list(zip(self.mapped("id"), self.mapped("name")))) result = super(ProjectTaskSubtask, self).write(vals) for r in self: if vals.get("state"): r.task_id.send_subtask_email( r.name, r.state, r.reviewer_id.id, r.user_id.id ) if self.env.user != r.reviewer_id and self.env.user != r.user_id: raise UserError( _("Only users related to that subtask can change state.") ) if vals.get("name"): r.task_id.send_subtask_email( r.name, r.state, r.reviewer_id.id, r.user_id.id, old_name=old_names[r.id], ) if self.env.user != r.reviewer_id and self.env.user != r.user_id: raise UserError( _("Only users related to that subtask can change state.") ) if vals.get("user_id"): r.task_id.send_subtask_email( r.name, r.state, r.reviewer_id.id, r.user_id.id ) return result @api.model def create(self, vals): result = super(ProjectTaskSubtask, self).create(vals) vals = self._add_missing_default_values(vals) task = self.env["project.task"].browse(vals.get("task_id")) task.send_subtask_email( vals["name"], vals["state"], vals["reviewer_id"], vals["user_id"] ) return result def change_state_done(self): for record in self: record.state = "done" def change_state_todo(self): for record in self: record.state = "todo" def change_state_cancelled(self): for record in self: record.state = "cancelled" def change_state_waiting(self): for record in self: record.state = "waiting" class Task(models.Model): _inherit = "project.task" subtask_ids = fields.One2many("project.task.subtask", "task_id", "Subtask") kanban_subtasks = fields.Text(compute="_compute_kanban_subtasks") default_user = fields.Many2one("res.users", compute="_compute_default_user") completion = fields.Integer("Completion", compute="_compute_completion") completion_xml = fields.Text(compute="_compute_completion_xml") def _compute_default_user(self): for record in self: if self.env.user != record.user_id and self.env.user != record.create_uid: record.default_user = record.user_id else: if self.env.user != record.user_id: record.default_user = record.user_id elif self.env.user != record.create_uid: record.default_user = record.create_uid elif ( self.env.user == record.create_uid and self.env.user == record.user_id ): record.default_user = self.env.user def _compute_kanban_subtasks(self): for record in self: result_string_td = "" result_string_wt = "" if record.subtask_ids: task_todo_ids = record.subtask_ids.filtered( lambda x: x.state == "todo" and x.user_id.id == record.env.user.id ) task_waiting_ids = record.subtask_ids.filtered( lambda x: x.state == "waiting" and x.user_id.id == record.env.user.id ) if task_todo_ids: tmp_string_td = escape(": {}".format(len(task_todo_ids))) result_string_td += "
  • TODO{}
  • ".format(tmp_string_td) if task_waiting_ids: tmp_string_wt = escape(": {}".format(len(task_waiting_ids))) result_string_wt += "
  • Waiting{}
  • ".format( tmp_string_wt ) record.kanban_subtasks = ( '
      ' + result_string_td + result_string_wt + "
    " ) def _compute_completion(self): for record in self: record.completion = record.task_completion() def _compute_completion_xml(self): for record in self: active_subtasks = record.subtask_ids and record.subtask_ids.filtered( lambda x: x.user_id.id == record.env.user.id and x.state != "cancelled" ) if not active_subtasks: record.completion_xml = """
    """ continue completion = record.task_completion() color = "bg-success-full" if completion < 50: color = "bg-danger-full" record.completion_xml = """
    Your Checklist:
    {0}%
    """.format( int(completion), color ) def task_completion(self): user_task_ids = self.subtask_ids.filtered( lambda x: x.user_id.id == self.env.user.id and x.state != "cancelled" ) if not user_task_ids: return 100 user_done_task_ids = user_task_ids.filtered(lambda x: x.state == "done") return (len(user_done_task_ids) / len(user_task_ids)) * 100 def send_subtask_email( self, subtask_name, subtask_state, subtask_reviewer_id, subtask_user_id, old_name=None, ): for r in self: body = "" reviewer = self.env["res.users"].browse(subtask_reviewer_id) user = self.env["res.users"].browse(subtask_user_id) state = SUBTASK_STATES[subtask_state] if subtask_state == "done": state = '' + state + "" if subtask_state == "todo": state = '' + state + "" if subtask_state == "cancelled": state = '' + state + "" if subtask_state == "waiting": state = '' + state + "" partner_ids = [] subtype = "project_task_subtask.subtasks_subtype" if user == self.env.user and reviewer == self.env.user: body = "

    " + "" + state + ": " + escape(subtask_name) subtype = False elif self.env.user == reviewer: body = ( "

    " + escape(user.name) + ",
    " + state + ": " + escape(subtask_name) ) partner_ids = [user.partner_id.id] elif self.env.user == user: body = ( "

    " + escape(reviewer.name) + ', I updated checklist item assigned to me:
    ' # noqa: B950 + state + ": " + escape(subtask_name) ) partner_ids = [reviewer.partner_id.id] else: body = ( "

    " + escape(user.name) + ", " + escape(reviewer.name) + ', I updated checklist item, now its assigned to ' + escape(user.name) + ":
    " + state + ": " + escape(subtask_name) ) partner_ids = [user.partner_id.id, reviewer.partner_id.id] if old_name: body = ( body + '
    Updated from
    ' + state + ": " + escape(old_name) + "

    " ) else: body = body + "

    " r.message_post( message_type="comment", subtime_xmlid=subtype, body=body, partner_ids=partner_ids, ) def copy(self, default=None): task = super(Task, self).copy(default) for subtask in self.subtask_ids: subtask.copy({"task_id": task.id, "state": subtask.state}) return task ================================================ FILE: project_task_subtask/readme/CONTRIBUTORS.md ================================================ - Ivan Yelizariev (https://github.com/yelizariev) - Rafael Manaev (https://github.com/manawi) - Ilmir Karamov (https://github.com/ilmir-k) - Ildar Nasyrov (https://github.com/iledarn) - Nicolas Jeudy (https://github.com/njeudy) - Alexandr Kolushov (https://github.com/KolushovAlexandr) - Almas Giniatullin (https://github.com/almas50) - Denis Mudarisov (https://github.com/trojikman) - Vildan Safin (https://github.com/Enigma228322) - Eugene Molotov (https://github.com/em230418) - Victor Bykov (https://github.com/BykovVik) ================================================ FILE: project_task_subtask/readme/DESCRIPTION.md ================================================ Use subtasks to control your tasks. Be ensure that all your tasks/subtasks are performed and not missed. Features: * Added new "Checklist" tab on task's form * When new subtask is created\changed, message is sent to user that assigned to this subtask * Only users related to subtask can change subtask parameters * All subtasks have a certain color, informing about their state * Each subtask has buttons to switch state: * DONE * TODO * CANCELLED * Added new "Checklist" menu * default filter: "My", "TODO" * optional group by: "Project", "Task", "User", "State" ================================================ FILE: project_task_subtask/readme/USAGE.md ================================================ * Create User1 and User2 in the ``Settings >> Users`` menu * Login as User1 * Go to ``Project >> Project >> All Tasks`` and open the ``Checklist`` tab * Create new subtask (Assigned to - User2) * Login as User2 * See message in Inbox like "TODO: subtask_name" * Change state of subtask to Cancelled/Done * You can see a message in Inbox "Cancelled: subtask_name" or "Done: subtask_name" accordingly. * You can see your TODOs on tasks in kanban view in the ``Project >> Project >> Tasks`` menu * The ``Project >> Project >> Checklist`` menu displays ALL subtasks in state TODO assigned to you and subtasks where you are Reviewer ================================================ FILE: project_task_subtask/security/ir.model.access.csv ================================================ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_task_subtask,project.task.subtask,model_project_task_subtask,project.group_project_user,1,1,1,0 ================================================ FILE: project_task_subtask/static/description/index.html ================================================

    Project Task Checklist

    Use checklist to be ensure that all your tasks are performed and to make easy control over them

    Key features:
    • create checklist for any tasks
    • track all subtasks that should be done and keep them under control
    • checklist items will be colored depending on their state
    • only users related to subtask can change subtask parameters
    • see instant email notifications in task mail thread and your Inbox

    How It Works

    Go to Project → Tasks menu and create/open a task. Here you can see new "Checklist" tab. Add items (hereinafter "subtasks") into your checklist.
    Specify "Description" and select "Assigned to", "Reviewer".

    • if a subtask has state "TODO", it's colored in red for user assigned to subtask
    • if a subtask has state "DONE", it's colored in green
    • if a subtask has state "CANCELLED", it's colored in grey

    If you mistakenly switch state to "DONE" or "CANCELLED", you will be able to revert state to TODO by clicking on

    All checklist changes and updates are tracked on task mail thread and you will receive instant email notifications to your Inbox

    You can see your TODOs on tasks in kanban view

    Track all your TODOs in one place and keep them under control. Go to the Project → Checklist menu to see them.

    Free Support

    You will get free support and assistance in case of any issues

    ================================================ FILE: project_task_subtask/static/src/css/kanban_styles.css ================================================ .task_progress { width: 40%; display: inline-block; font-size: 10px; } .task_progress { width: 40%; display: inline-block; font-size: 10px; } .task_progress .task_progress_bar { width: 85%; display: inline-block; margin-bottom: 0px; height: 10px; } .task_progress .task_progress_bar_done { max-width: 100%; min-width: 3%; } .task_progress .task_completion { width: 10%; display: inline-block; height: 13px; } .kanban_subtasks { width: 55%; display: inline-block; font-size: 10px; } .kanban_subtasks ul { -webkit-padding-start: 30px; } ================================================ FILE: project_task_subtask/static/src/js/one2many_renderer.js ================================================ odoo.define("project_task_subtask.one2many_renderer", function (require) { "use strict"; var FieldOne2Many = require("web.relational_fields").FieldOne2Many; var BasicModel = require("web.BasicModel"); var core = require("web.core"); var QWeb = core.qweb; FieldOne2Many.include({ check_task_tree_mode: function () { if ( this.view && this.view.arch.tag === "tree" && this.record && this.record.model === "project.task" && this.name === "subtask_ids" ) { return true; } return false; }, sort_data: function () { var user_id = this.record.context.uid; var new_rows = _.filter(this.value.data, function (d) { return !d.res_id; }); var data = _.difference(this.value.data, new_rows); _.each(data, function (d) { d.u_name = d.data.user_id.data.display_name; }); var name_index = _.sortBy( _.uniq( _.map(data, function (d) { return d.data.user_id.data.display_name; }) ) ); data = _.sortBy(data, "u_name"); _.each(data, function (d) { d.deadline = d.data.deadline; if (d.data.user_id.data.id === user_id) { d.index = 0; } else { d.index = (_.indexOf(name_index, d.data.user_id.data.display_name) + 1) * 1000000; } }); data = _.sortBy(data, "deadline"); _.each(data, function (d) { d.index += _.indexOf(data, d); if (!d.deadline) { d.index += 90000; } if (d.data.state === "todo") { // Continue } else if (d.data.state === "waiting") { d.index += 100000; } else if (d.data.state === "done") { d.index += 400000; } else { // Makes cancelled subtasks stay last in line d.index += (name_index.length + 2) * 1000000; if (d.data.user_id.data.id !== user_id) { d.index += (_.indexOf(name_index, d.data.user_id.data.display_name) + 1) * 1000000; } } }); data = _.sortBy(data, "index"); _.each(new_rows, function (r) { data.push(r); }); this.default_sorting = this.value.data; this.value.data = data; }, _render: function () { if (this.check_task_tree_mode() && this.getParent().list_is_sorted) { this.sort_data(); } return this._super(arguments); }, reset: function (record, ev, fieldChanged) { var self = this; return this._super.apply(this, arguments).then(function (res) { if (self.check_task_tree_mode() && self.getParent().list_is_sorted) { self._render(); } }); }, _renderButtons: function () { var self = this; if (this.check_task_tree_mode()) { this.$buttons = $( QWeb.render("SubtaskSortButtons", { check_button: this.getParent().list_is_sorted, }) ); this.$buttons.on( "click", ".o_pager_sort", this._update_custom_sort_buttons.bind(this) ); this.$buttons.on( "click", ".o_pager_unsort", this._update_custom_unsort_buttons.bind(this) ); } return this._super(arguments); }, _update_custom_sort_buttons: function () { this.getParent().list_is_sorted = true; this.default_sorting = this.value.data; this._render(); }, _update_custom_unsort_buttons: function () { this.getParent().list_is_sorted = false; this.value.data = this.default_sorting; this._render(); }, }); BasicModel.include({ _sortList: function (list) { // Taken from odoo if (!list.static) { // Only sort x2many lists return; } var self = this; // ----- if (list.model === "project.task.subtask" && list.orderedResIDs) { var rows = []; var new_rows = []; _.each(list.data, function (d) { var r = self.localData[d]; if (Number(r.res_id) === r.res_id) { rows.push(r); } else { new_rows.push(r); } }); rows = this.sort_data(rows, list.context.uid, this); _.each(new_rows, function (r) { rows.push(r); }); list.orderedResIDs = _.pluck(rows, "res_id"); return this._setDataInRange(list); } return this._super(list); }, sort_data: function (data, user_id, parent) { user_id = user_id || 1; _.each(data, function (d) { d.u_name = parent.localData[d.data.user_id].data.display_name; }); var name_index = _.sortBy( _.uniq( _.map(data, function (d) { return parent.localData[d.data.user_id].data.display_name; }) ) ); data = _.sortBy(data, "u_name"); _.each(data, function (d) { d.deadline = d.data.deadline; if (parent.localData[d.data.user_id].data.id === user_id) { d.index = 0; } else { d.index = (_.indexOf( name_index, parent.localData[d.data.user_id].data.display_name ) + 1) * 1000000; } }); data = _.sortBy(data, "deadline"); _.each(data, function (d) { d.index += _.indexOf(data, d); if (!d.deadline) { d.index += 90000; } if (d.data.state === "todo") { // Continue } else if (d.data.state === "waiting") { d.index += 100000; } else if (d.data.state === "done") { d.index += 400000; } else { d.index += 700000; } }); return _.sortBy(data, "index"); }, }); }); ================================================ FILE: project_task_subtask/static/src/js/tours/tour.js ================================================ odoo.define("project_task_subtask.tour", function (require) { "use strict"; var core = require("web.core"); var tour = require("web_tour.tour"); var _t = core._t; var steps = [ tour.stepUtils.showAppsMenuItem(), { trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', content: _t( "Want a better way to manage your projects? It starts here." ), position: "right", edition: "community", }, { trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', content: _t( "Want a better way to manage your projects? It starts here." ), position: "bottom", edition: "enterprise", }, { trigger: ".o_project_kanban_main", content: "open project", timeout: 10000, }, { trigger: ".o_loading", content: "waiting for loading to finish", timeout: 5000, }, { trigger: ".o_content", content: "just click", timeout: 1000, }, { trigger: ".oe_kanban_content", content: "open task", timeout: 20000, }, { trigger: ".o_pager_sort", content: "sort", timeout: 10000, }, { trigger: ".o_pager_unsort", content: "unsort", timeout: 10000, }, ]; tour.register("task_subtask", {url: "/web"}, steps); }); ================================================ FILE: project_task_subtask/static/src/xml/templates.xml ================================================ ================================================ FILE: project_task_subtask/tests/__init__.py ================================================ # License MIT (https://opensource.org/licenses/MIT). from . import test_subtask_sort_button ================================================ FILE: project_task_subtask/tests/test_subtask_sort_button.py ================================================ import odoo.tests class TestUi(odoo.tests.HttpCase): def test_01_subtask_sort_button(self): self.env["ir.module.module"].search( [("name", "=", "project_task_subtask")], limit=1 ).state = "installed" self.start_tour("/web", "task_subtask", login="admin") ================================================ FILE: project_task_subtask/views/assets.xml ================================================