diff --git a/.copier-answers.yml b/.copier-answers.yml index a6f8f820df..feec5e489f 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,10 +1,11 @@ # Do NOT update manually; changes here will be overwritten by Copier -_commit: v1.29 +_commit: v1.39 _src_path: gh:oca/oca-addons-repo-template +additional_ruff_rules: [] ci: GitHub convert_readme_fragments_to_markdown: false enable_checklog_odoo: false -generate_requirements_txt: true +generate_requirements_txt: false github_check_license: true github_ci_extra_env: {} github_enable_codecov: true @@ -22,5 +23,5 @@ repo_name: helpdesk repo_slug: helpdesk repo_website: https://github.com/OCA/helpdesk use_pyproject_toml: false -use_ruff: false +use_ruff: true diff --git a/.flake8 b/.flake8 deleted file mode 100644 index e397e8ed4e..0000000000 --- a/.flake8 +++ /dev/null @@ -1,12 +0,0 @@ -[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 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..e0d56685a9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +test-requirements.txt merge=union diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index afd7524ef0..43b82fe8e7 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -17,6 +17,8 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.11" + cache: 'pip' + cache-dependency-path: '.pre-commit-config.yaml' - name: Get python version run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - uses: actions/cache@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5d0f95283c..5ec4eb783e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: makepot: "true" services: postgres: - image: postgres:12.0 + image: postgres:12 env: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo @@ -63,6 +63,13 @@ jobs: run: oca_init_test_database - name: Run tests run: oca_run_tests + - name: Upload screenshots from JS tests + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: Screenshots of failed JS tests - ${{ matrix.name }}${{ join(matrix.include) }} + path: /tmp/odoo_tests/${{ env.PGDATABASE }} + if-no-files-found: ignore - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index 0ec187efd1..0000000000 --- a/.isort.cfg +++ /dev/null @@ -1,13 +0,0 @@ -[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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec2731d987..c0a9d43732 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: language: fail files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools - rev: d5fab7ee87fceee858a3d01048c78a548974d935 + rev: f9b919b9868143135a9c9cb03021089cabba8223 hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons @@ -60,21 +60,6 @@ repos: - id: oca-checks-po args: - --disable=po-pretty-format - - repo: https://github.com/myint/autoflake - rev: v1.6.1 - 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.8.0 - hooks: - - id: black - repo: local hooks: - id: prettier @@ -104,6 +89,7 @@ repos: additional_dependencies: - "eslint@8.24.0" - "eslint-plugin-jsdoc@" + - "globals@" - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 hooks: @@ -126,35 +112,16 @@ repos: - id: check-xml - id: mixed-line-ending args: ["--fix=lf"] - - repo: https://github.com/asottile/pyupgrade - rev: v2.38.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 + rev: 3.3.2 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: 5.0.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.3 hooks: - - id: flake8 - name: flake8 - additional_dependencies: ["flake8-bugbear==21.9.2"] + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format - repo: https://github.com/OCA/pylint-odoo rev: v8.0.19 hooks: diff --git a/.pylintrc b/.pylintrc index 554913276b..0a521c31ff 100644 --- a/.pylintrc +++ b/.pylintrc @@ -25,19 +25,25 @@ 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, + openerp-exception-warning, + redundant-modulename-xml, + relative-import, + rst-syntax-error, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + assignment-from-none, + attribute-deprecated, + dangerous-default-value, + development-status-allowed, + duplicate-key, + eval-used, license-allowed, manifest-author-string, manifest-deprecated-key, @@ -48,73 +54,68 @@ enable=anomalous-backslash-in-string, 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, - attribute-string-redundant, character-not-valid-in-resource-link, - consider-merging-classes-inherited, - context-overridden, create-user-wo-reset-password, dangerous-filter-wo-user, dangerous-qweb-replace-wo-priority, deprecated-data-xml-node, deprecated-openerp-xml-node, duplicate-po-message-definition, - except-pass, file-not-used, + missing-newline-extrafiles, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + str-format-used, + unnecessary-utf8-coding-comment, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + attribute-string-redundant, + consider-merging-classes-inherited, + context-overridden, + except-pass, invalid-commit, manifest-maintainers-list, - missing-newline-extrafiles, missing-readme, missing-return, odoo-addons-relative-import, - old-api7-method-defined, - po-msgstr-variables, - po-syntax-error, renamed-field-parameter, resource-not-exist, - str-format-used, test-folder-imported, translation-contains-variable, translation-positional-used, - unnecessary-utf8-coding-comment, website-manifest-key-not-valid-uri, - xml-attribute-translatable, - xml-deprecated-qweb-directive, - xml-deprecated-tree-attribute, external-request-timeout, - # messages that do not cause the lint step to fail - consider-merging-classes-inherited, + missing-manifest-dependency, + too-complex,, 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, + unnecessary-utf8-coding-comment, + # messages that do not cause the lint step to fail + consider-merging-classes-inherited, + deprecated-module, + invalid-commit, + missing-readme, + odoo-addons-relative-import, redefined-builtin, - too-complex, - unnecessary-utf8-coding-comment + manifest-external-assets [REPORTS] diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory index 7a0cd4efef..098393aadb 100644 --- a/.pylintrc-mandatory +++ b/.pylintrc-mandatory @@ -17,19 +17,25 @@ 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, + openerp-exception-warning, + redundant-modulename-xml, + relative-import, + rst-syntax-error, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + assignment-from-none, + attribute-deprecated, + dangerous-default-value, + development-status-allowed, + duplicate-key, + eval-used, license-allowed, manifest-author-string, manifest-deprecated-key, @@ -40,56 +46,50 @@ enable=anomalous-backslash-in-string, 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, - attribute-string-redundant, character-not-valid-in-resource-link, - consider-merging-classes-inherited, - context-overridden, create-user-wo-reset-password, dangerous-filter-wo-user, dangerous-qweb-replace-wo-priority, deprecated-data-xml-node, deprecated-openerp-xml-node, duplicate-po-message-definition, - except-pass, file-not-used, + missing-newline-extrafiles, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + str-format-used, + unnecessary-utf8-coding-comment, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + attribute-string-redundant, + consider-merging-classes-inherited, + context-overridden, + except-pass, invalid-commit, manifest-maintainers-list, - missing-newline-extrafiles, missing-readme, missing-return, odoo-addons-relative-import, - old-api7-method-defined, - po-msgstr-variables, - po-syntax-error, renamed-field-parameter, resource-not-exist, - str-format-used, test-folder-imported, translation-contains-variable, translation-positional-used, - unnecessary-utf8-coding-comment, website-manifest-key-not-valid-uri, - xml-attribute-translatable, - xml-deprecated-qweb-directive, - xml-deprecated-tree-attribute, external-request-timeout [REPORTS] diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000000..8e8eccb6d5 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,31 @@ + +target-version = "py310" +fix = true + +[lint] +extend-select = [ + "B", + "C90", + "E501", # line too long (default 88) + "I", # isort + "UP", # pyupgrade +] +extend-safe-fixes = ["UP008"] +exclude = ["setup/*"] + +[format] +exclude = ["setup/*"] + +[per-file-ignores] +"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py +"__manifest__.py" = ["B018"] # useless expression + +[isort] +section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"] + +[isort.sections] +"odoo" = ["odoo"] +"odoo-addons" = ["odoo.addons"] + +[mccabe] +max-complexity = 16 diff --git a/README.md b/README.md index 4a3a68232b..0799088c91 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ +[![Support the OCA](https://odoo-community.org/readme-banner-image)](https://odoo-community.org/get-involved?utm_source=repo-readme) + +# helpdesk [![Runboat](https://img.shields.io/badge/runboat-Try%20me-875A7B.png)](https://runboat.odoo-community.org/builds?repo=OCA/helpdesk&target_branch=16.0) [![Pre-commit Status](https://github.com/OCA/helpdesk/actions/workflows/pre-commit.yml/badge.svg?branch=16.0)](https://github.com/OCA/helpdesk/actions/workflows/pre-commit.yml?query=branch%3A16.0) [![Build Status](https://github.com/OCA/helpdesk/actions/workflows/test.yml/badge.svg?branch=16.0)](https://github.com/OCA/helpdesk/actions/workflows/test.yml?query=branch%3A16.0) @@ -7,8 +10,6 @@ -# helpdesk - TODO: add repo description. diff --git a/helpdesk_mgmt/controllers/myaccount.py b/helpdesk_mgmt/controllers/myaccount.py index a5071dae50..100cd923db 100644 --- a/helpdesk_mgmt/controllers/myaccount.py +++ b/helpdesk_mgmt/controllers/myaccount.py @@ -9,7 +9,8 @@ from odoo.osv.expression import AND, OR from odoo.tools import groupby as groupbyelem -from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager +from odoo.addons.portal.controllers.portal import CustomerPortal +from odoo.addons.portal.controllers.portal import pager as portal_pager class CustomerPortalHelpdesk(CustomerPortal): @@ -45,7 +46,7 @@ def portal_my_tickets( search=None, search_in=None, groupby=None, - **kw + **kw, ): HelpdeskTicket = request.env["helpdesk.ticket"] # Avoid error if the user does not have access. @@ -253,7 +254,7 @@ def _ticket_get_order(self, order, groupby): field_name = groupby_mapping.get(groupby, "") if not field_name: return order - return "%s, %s" % (field_name, order) + return f"{field_name}, {order}" def _get_searchbar_filters(self): filters = { diff --git a/helpdesk_mgmt/models/helpdesk_ticket.py b/helpdesk_mgmt/models/helpdesk_ticket.py index a513c2092f..d06145c78a 100644 --- a/helpdesk_mgmt/models/helpdesk_ticket.py +++ b/helpdesk_mgmt/models/helpdesk_ticket.py @@ -49,7 +49,7 @@ def _read_group_stage_ids(self, stages, domain, order): compute="_compute_user_id", store=True, readonly=False, - domain="team_id and [('share', '=', False),('id', 'in', user_ids)] or [('share', '=', False)]", # noqa: B950 + domain="team_id and [('share', '=', False),('id', 'in', user_ids)] or [('share', '=', False)]", # noqa: E501 ) user_ids = fields.Many2many( comodel_name="res.users", related="team_id.user_ids", string="Users" diff --git a/helpdesk_mgmt/models/helpdesk_ticket_category.py b/helpdesk_mgmt/models/helpdesk_ticket_category.py index 17718883b8..fe25c8f909 100644 --- a/helpdesk_mgmt/models/helpdesk_ticket_category.py +++ b/helpdesk_mgmt/models/helpdesk_ticket_category.py @@ -2,7 +2,6 @@ class HelpdeskCategory(models.Model): - _name = "helpdesk.ticket.category" _description = "Helpdesk Ticket Category" _order = "sequence, id" diff --git a/helpdesk_mgmt/models/helpdesk_ticket_channel.py b/helpdesk_mgmt/models/helpdesk_ticket_channel.py index 62c0668de2..41f6c6b857 100644 --- a/helpdesk_mgmt/models/helpdesk_ticket_channel.py +++ b/helpdesk_mgmt/models/helpdesk_ticket_channel.py @@ -2,7 +2,6 @@ class HelpdeskTicketChannel(models.Model): - _name = "helpdesk.ticket.channel" _description = "Helpdesk Ticket Channel" _order = "sequence, id" diff --git a/helpdesk_mgmt/models/helpdesk_ticket_team.py b/helpdesk_mgmt/models/helpdesk_ticket_team.py index 75df44609b..186c514057 100644 --- a/helpdesk_mgmt/models/helpdesk_ticket_team.py +++ b/helpdesk_mgmt/models/helpdesk_ticket_team.py @@ -3,7 +3,6 @@ class HelpdeskTeam(models.Model): - _name = "helpdesk.ticket.team" _description = "Helpdesk Ticket Team" _inherit = ["mail.thread", "mail.alias.mixin"] diff --git a/helpdesk_mgmt/models/ir_http.py b/helpdesk_mgmt/models/ir_http.py index e26bfdbf9f..eefd3ca92c 100644 --- a/helpdesk_mgmt/models/ir_http.py +++ b/helpdesk_mgmt/models/ir_http.py @@ -8,5 +8,5 @@ class IrHttp(models.AbstractModel): @classmethod def _get_translation_frontend_modules_name(cls): - mods = super(IrHttp, cls)._get_translation_frontend_modules_name() + mods = super()._get_translation_frontend_modules_name() return mods + ["helpdesk_mgmt"] diff --git a/helpdesk_mgmt/models/res_partner.py b/helpdesk_mgmt/models/res_partner.py index f5aceed362..8d96c5a8ee 100644 --- a/helpdesk_mgmt/models/res_partner.py +++ b/helpdesk_mgmt/models/res_partner.py @@ -33,7 +33,7 @@ def _compute_helpdesk_ticket_count(self): ) count_active = record.helpdesk_ticket_active_count count = record.helpdesk_ticket_count - record.helpdesk_ticket_count_string = "{} / {}".format(count_active, count) + record.helpdesk_ticket_count_string = f"{count_active} / {count}" def action_view_helpdesk_tickets(self): return { diff --git a/helpdesk_mgmt/tests/common.py b/helpdesk_mgmt/tests/common.py index a41e5f35f4..9b2e6b403a 100644 --- a/helpdesk_mgmt/tests/common.py +++ b/helpdesk_mgmt/tests/common.py @@ -52,8 +52,7 @@ def setUpClass(cls): def _create_ticket(self, team, user=False): ticket = self.env["helpdesk.ticket"].create( { - "name": "Ticket %s (%s)" - % (team.name, user.login if user else "unassigned"), + "name": f"Ticket {team.name} ({user.login if user else 'unassigned'})", "description": "Description", "team_id": team.id, "user_id": user.id if user else False, diff --git a/helpdesk_mgmt/tests/test_helpdesk_ticket.py b/helpdesk_mgmt/tests/test_helpdesk_ticket.py index ebe0bbb198..089ff1308e 100644 --- a/helpdesk_mgmt/tests/test_helpdesk_ticket.py +++ b/helpdesk_mgmt/tests/test_helpdesk_ticket.py @@ -137,7 +137,7 @@ def test_helpdesk_ticket_message_new(self): try: t = Ticket.message_new(msg_dict) except Exception as error: - self.fail("%s: %s" % (type(error), error)) + self.fail(f"{type(error)}: {error}") self.assertEqual(t.name, title, "The ticket should have the correct title.") title = "New title" @@ -145,7 +145,7 @@ def test_helpdesk_ticket_message_new(self): try: t.message_update(msg_dict, update_vals) except Exception as error: - self.fail("%s: %s" % (type(error), error)) + self.fail(f"{type(error)}: {error}") self.assertEqual( t.name, title, "The ticket should have the correct (new) title." ) diff --git a/helpdesk_mgmt/tests/test_res_partner.py b/helpdesk_mgmt/tests/test_res_partner.py index 99dde5c96c..8a349c9402 100644 --- a/helpdesk_mgmt/tests/test_res_partner.py +++ b/helpdesk_mgmt/tests/test_res_partner.py @@ -21,8 +21,8 @@ def setUp(self): self.tickets.append( self.ticket_obj.create( { - "name": "Nice ticket {}".format(i), - "description": "Nice ticket {} description".format(i), + "name": f"Nice ticket {i}", + "description": f"Nice ticket {i} description", } ) ) diff --git a/helpdesk_mgmt_activity/models/helpdesk_ticket.py b/helpdesk_mgmt_activity/models/helpdesk_ticket.py index bc95fa223f..d8990b0626 100644 --- a/helpdesk_mgmt_activity/models/helpdesk_ticket.py +++ b/helpdesk_mgmt_activity/models/helpdesk_ticket.py @@ -79,7 +79,7 @@ def _compute_next_stage_id(self): next_stage = ( stages.filtered( lambda stage, _cur_stage=current_stage: stage.sequence - > current_stage.sequence + > _cur_stage.sequence )[:1] or current_stage ) @@ -94,7 +94,7 @@ def _compute_record_ref(self): continue try: self.env[rec.res_model].browse(rec.res_id).check_access_rule("read") - rec.record_ref = "%s,%s" % (rec.res_model, rec.res_id) + rec.record_ref = f"{rec.res_model},{rec.res_id}" except Exception: rec.record_ref = None diff --git a/helpdesk_mgmt_assign_method/models/helpdesk_ticket.py b/helpdesk_mgmt_assign_method/models/helpdesk_ticket.py index 6924223e17..7e5b6b1bf6 100644 --- a/helpdesk_mgmt_assign_method/models/helpdesk_ticket.py +++ b/helpdesk_mgmt_assign_method/models/helpdesk_ticket.py @@ -34,4 +34,4 @@ def create(self, vals): if team_id and not vals.get("user_id"): team = self.env["helpdesk.ticket.team"].browse(team_id) vals["user_id"] = team.get_new_user().id - return super(HelpdeskTicket, self).create(vals) + return super().create(vals) diff --git a/helpdesk_mgmt_assign_method/models/helpdesk_ticket_team.py b/helpdesk_mgmt_assign_method/models/helpdesk_ticket_team.py index 10203cc742..92ce6a7252 100644 --- a/helpdesk_mgmt_assign_method/models/helpdesk_ticket_team.py +++ b/helpdesk_mgmt_assign_method/models/helpdesk_ticket_team.py @@ -45,7 +45,8 @@ def _check_user_assignation(self): if not team.user_ids and team.assign_method != "manual": raise ValidationError( _( - "You must have team members assigned to change the assignation method." + "You must have team members assigned to change " + "the assignation method." ) ) diff --git a/helpdesk_mgmt_fieldservice/models/res_partner.py b/helpdesk_mgmt_fieldservice/models/res_partner.py index bc98990c07..1eda65fee1 100644 --- a/helpdesk_mgmt_fieldservice/models/res_partner.py +++ b/helpdesk_mgmt_fieldservice/models/res_partner.py @@ -15,5 +15,5 @@ def action_view_helpdesk_tickets(self): default_partner_id=self.id, default_fsm_location_id=self.service_location_id.id, ) - return super(ResPartner, self).action_view_helpdesk_tickets() + return super().action_view_helpdesk_tickets() return super().action_view_helpdesk_tickets() diff --git a/helpdesk_mgmt_merge/tests/test_helpdesk_mgmt_merge.py b/helpdesk_mgmt_merge/tests/test_helpdesk_mgmt_merge.py index 34d9e268fd..0316091f7a 100644 --- a/helpdesk_mgmt_merge/tests/test_helpdesk_mgmt_merge.py +++ b/helpdesk_mgmt_merge/tests/test_helpdesk_mgmt_merge.py @@ -4,7 +4,7 @@ class TestHelpdeskTicketMerge(common.TransactionCase): @classmethod def setUpClass(cls): - super(TestHelpdeskTicketMerge, cls).setUpClass() + super().setUpClass() cls.HelpdeskTicketMerge = cls.env["helpdesk.ticket.merge"] cls.ticket_1 = cls._create_ticket(cls, "Ticket 1", "Description for Ticket 1") cls.ticket_2 = cls._create_ticket(cls, "Ticket 2", "Description for Ticket 2") diff --git a/helpdesk_mgmt_merge/wizard/helpdesk_ticket_merge.py b/helpdesk_mgmt_merge/wizard/helpdesk_ticket_merge.py index e56f626c39..36f544f015 100644 --- a/helpdesk_mgmt_merge/wizard/helpdesk_ticket_merge.py +++ b/helpdesk_mgmt_merge/wizard/helpdesk_ticket_merge.py @@ -68,7 +68,7 @@ def merge_tickets(self): for ticket in merged_tickets: self._add_message( "to", - f'{self.dst_ticket_id.number}', # noqa: B950 + f'{self.dst_ticket_id.number}', # noqa: E501 ticket, ) ticket_numbers = ", ".join( @@ -106,7 +106,7 @@ def _merge_followers(self, merged_tickets): ) def default_get(self, fields): - result = super(HelpdeskTicketMerge, self).default_get(fields) + result = super().default_get(fields) selected_tickets = self.env["helpdesk.ticket"].browse( self.env.context.get("active_ids", False) ) diff --git a/helpdesk_mgmt_portal_follower/README.rst b/helpdesk_mgmt_portal_follower/README.rst index 2ec7052f8c..9327d7544d 100644 --- a/helpdesk_mgmt_portal_follower/README.rst +++ b/helpdesk_mgmt_portal_follower/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + =============== Portal Follower =============== @@ -13,7 +17,7 @@ Portal Follower .. |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-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhelpdesk-lightgray.png?logo=github diff --git a/helpdesk_mgmt_portal_follower/__manifest__.py b/helpdesk_mgmt_portal_follower/__manifest__.py index 1c897f54b4..32794aa50a 100644 --- a/helpdesk_mgmt_portal_follower/__manifest__.py +++ b/helpdesk_mgmt_portal_follower/__manifest__.py @@ -3,7 +3,8 @@ "summary": "Add ticket followers from website portal", "author": ( "Advanced Programming Solutions S.L. - APSL - Nagarro, " - "Bernat Obrador, Patryk Pyczko, Miquel Pascual, Odoo Community Association (OCA)" + "Bernat Obrador, Patryk Pyczko, Miquel Pascual, " + "Odoo Community Association (OCA)" ), "license": "AGPL-3", "maintainers": ["BernatObrador", "ppyczko", "mpascuall"], diff --git a/helpdesk_mgmt_portal_follower/controllers/main.py b/helpdesk_mgmt_portal_follower/controllers/main.py index bbee7484aa..c20f686efb 100644 --- a/helpdesk_mgmt_portal_follower/controllers/main.py +++ b/helpdesk_mgmt_portal_follower/controllers/main.py @@ -7,7 +7,7 @@ class HelpdeskTicketController(HelpdeskTicketController): @http.route("/submitted/ticket", type="http", auth="user", website=True, csrf=True) def submit_ticket(self, **kw): - res = super(HelpdeskTicketController, self).submit_ticket(**kw) + res = super().submit_ticket(**kw) ticket_id = res.location.split("/")[-1] new_ticket = request.env["helpdesk.ticket"].browse(int(ticket_id)) if kw.get("followers"): diff --git a/helpdesk_mgmt_portal_follower/static/description/index.html b/helpdesk_mgmt_portal_follower/static/description/index.html index f2c7908dee..b7aefc2cfd 100644 --- a/helpdesk_mgmt_portal_follower/static/description/index.html +++ b/helpdesk_mgmt_portal_follower/static/description/index.html @@ -3,7 +3,7 @@ -Portal Follower +README.rst -
-

Portal Follower

+
+ + +Odoo Community Association + +
+

Portal Follower

-

Beta License: AGPL-3 OCA/helpdesk Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/helpdesk Translate me on Weblate Try me on Runboat

This module adds the posibilty to add followers to a helpdesk ticket from the helpdesk form at the website portal.

Table of contents

@@ -390,14 +395,14 @@

Portal Follower

-

Usage

+

Usage

To make it work you just need to add the emails of the wanted followers to the Emails in Copy input splitted by comas.

-

Known issues / Roadmap

+

Known issues / Roadmap

-

Known Caveats

+

Known Caveats

  1. Spam Risks:
    • Allowing users to input any email address could lead to spam if @@ -424,7 +429,7 @@

      Known Caveats

-

Bug Tracker

+

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 @@ -432,9 +437,9 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Advanced Programming Solutions S.L. - APSL - Nagarro
  • Bernat Obrador
  • @@ -443,7 +448,7 @@

    Authors

-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -469,5 +474,6 @@

Maintainers

+
diff --git a/helpdesk_mgmt_project/models/helpdesk_ticket.py b/helpdesk_mgmt_project/models/helpdesk_ticket.py index 217ac37fc2..f7acc74179 100644 --- a/helpdesk_mgmt_project/models/helpdesk_ticket.py +++ b/helpdesk_mgmt_project/models/helpdesk_ticket.py @@ -2,7 +2,6 @@ class HelpdeskTicket(models.Model): - _inherit = "helpdesk.ticket" project_id = fields.Many2one(string="Project", comodel_name="project.project") diff --git a/helpdesk_mgmt_project_domain/models/helpdesk_ticket.py b/helpdesk_mgmt_project_domain/models/helpdesk_ticket.py index 7322e5c959..11e1266e9c 100644 --- a/helpdesk_mgmt_project_domain/models/helpdesk_ticket.py +++ b/helpdesk_mgmt_project_domain/models/helpdesk_ticket.py @@ -240,7 +240,7 @@ def _safe_eval_domain_text(self, expr): return [] try: dom = safe_eval(expr, {"uid": self.env.uid}) - if isinstance(dom, (list, tuple)): + if isinstance(dom, list | tuple): return expression.normalize_domain(list(dom)) _logger.warning( "Evaluated domain is not a list/tuple (expr=%s, type=%s)", @@ -286,7 +286,7 @@ def _run_python_domain(self, python_code, base_domain=None, company=None): try: maybe = safe_eval(python_code.strip(), safe_globals) - if isinstance(maybe, (list, tuple)): + if isinstance(maybe, list | tuple): return expression.normalize_domain(list(maybe)) except Exception as e: _logger.debug("Failed to evaluate Python domain as expression: %s", e) @@ -295,7 +295,7 @@ def _run_python_domain(self, python_code, base_domain=None, company=None): try: safe_eval(python_code.strip(), eval_context, mode="exec", nocopy=True) dom = eval_context.get("domain", []) - if isinstance(dom, (list, tuple)): + if isinstance(dom, list | tuple): return expression.normalize_domain(list(dom)) if dom: _logger.warning( @@ -397,14 +397,14 @@ def _get_task_domain_dynamic(self): def _domain_contains_field(self, domain, field_name): """True if domain contains any leaf referencing the given field name.""" - if not domain or not isinstance(domain, (list, tuple)): + if not domain or not isinstance(domain, list | tuple): return False for token in domain: if isinstance(token, str): continue - if isinstance(token, (list, tuple)): + if isinstance(token, list | tuple): if len(token) == 3 and token[0] == field_name: return True diff --git a/helpdesk_mgmt_project_domain/models/helpdesk_ticket_team.py b/helpdesk_mgmt_project_domain/models/helpdesk_ticket_team.py index 578a61e496..f1f5e6d668 100644 --- a/helpdesk_mgmt_project_domain/models/helpdesk_ticket_team.py +++ b/helpdesk_mgmt_project_domain/models/helpdesk_ticket_team.py @@ -56,7 +56,8 @@ class HelpdeskTicketTeam(models.Model): string="Project Domain Python Code", default=DEFAULT_PYTHON_CODE, help="Python code to generate dynamic project domain based on ticket data. " - "This domain will be automatically combined with company and team domains using AND. " + "This domain will be automatically combined " + "with company and team domains using AND. " "The code can either assign to 'domain' variable OR return a list directly. " "Available variables: ticket, env, user, company, AND, OR, normalize.", ) @@ -71,7 +72,8 @@ class HelpdeskTicketTeam(models.Model): string="Task Domain Python Code", default=DEFAULT_TASK_PYTHON_CODE, help="Python code to generate dynamic task domain based on ticket data. " - "This domain will be automatically combined with company and team domains using AND. " + "This domain will be automatically combined with company " + "and team domains using AND. " "The code can either assign to 'domain' variable OR return a list directly. " "Available variables: ticket, env, user, company, AND, OR, normalize.", ) diff --git a/helpdesk_mgmt_project_domain/models/res_company.py b/helpdesk_mgmt_project_domain/models/res_company.py index ed9db241a3..09da3e8f8e 100644 --- a/helpdesk_mgmt_project_domain/models/res_company.py +++ b/helpdesk_mgmt_project_domain/models/res_company.py @@ -5,7 +5,6 @@ class ResCompany(models.Model): - _inherit = "res.company" helpdesk_mgmt_project_domain = fields.Char( diff --git a/helpdesk_mgmt_project_domain/models/res_config_settings.py b/helpdesk_mgmt_project_domain/models/res_config_settings.py index b73dea8f5d..70284a947c 100644 --- a/helpdesk_mgmt_project_domain/models/res_config_settings.py +++ b/helpdesk_mgmt_project_domain/models/res_config_settings.py @@ -5,7 +5,6 @@ class ResConfigSettings(models.TransientModel): - _inherit = "res.config.settings" helpdesk_mgmt_project_domain = fields.Char( diff --git a/helpdesk_mgmt_project_domain/tests/test_helpdesk_ticket.py b/helpdesk_mgmt_project_domain/tests/test_helpdesk_ticket.py index c87940a031..be603c8a75 100644 --- a/helpdesk_mgmt_project_domain/tests/test_helpdesk_ticket.py +++ b/helpdesk_mgmt_project_domain/tests/test_helpdesk_ticket.py @@ -219,7 +219,7 @@ def test_task_domain_filters_and_domain_contains_field(self): project_id_filters = [ leaf for leaf in normalized_task_domain - if isinstance(leaf, (list, tuple)) + if isinstance(leaf, list | tuple) and len(leaf) == 3 and leaf[0] == "project_id" and leaf[1] == "=" diff --git a/helpdesk_mgmt_stage_validation/tests/test_helpdesk_ticket_stage_validation.py b/helpdesk_mgmt_stage_validation/tests/test_helpdesk_ticket_stage_validation.py index 7974a08989..0c368e1478 100644 --- a/helpdesk_mgmt_stage_validation/tests/test_helpdesk_ticket_stage_validation.py +++ b/helpdesk_mgmt_stage_validation/tests/test_helpdesk_ticket_stage_validation.py @@ -50,13 +50,8 @@ def get_validate_message(self, ticket, stage): fields = ", ".join(fields) if fields: validate_message = _( - "Ticket %(ticket)s can't be moved to the stage %(stage)s until " - "the following fields are set: %(fields)s." - % { - "ticket": ticket.name, - "stage": stage.name, - "fields": fields, - } + f"Ticket {ticket.name} can't be moved to the stage {stage.name} until " + f"the following fields are set: {fields}." ) return validate_message diff --git a/helpdesk_mgmt_template/tests/test_helpdesk_ticket.py b/helpdesk_mgmt_template/tests/test_helpdesk_ticket.py index b6a4949713..2e580c9d8a 100644 --- a/helpdesk_mgmt_template/tests/test_helpdesk_ticket.py +++ b/helpdesk_mgmt_template/tests/test_helpdesk_ticket.py @@ -34,7 +34,8 @@ def setUpClass(cls): def test_set_category(self): """ - Test that setting a category on a ticket correctly sets the category_id and description. + Test that setting a category on a ticket correctly + sets the category_id and description. """ # Check that the category_id is initially empty self.assertFalse( @@ -83,7 +84,8 @@ def test_check_available_team_categories(self): msg="A team should not have categories attached to it.", ) - # Assign a team to the ticket and check that the categories are linked to the team. + # Assign a team to the ticket and check that + # the categories are linked to the team. self.ticket_a_user_own.team_id = self.team_c.id related_category_ids = [self.category_1.id, self.category_3.id] self.assertEqual( @@ -92,7 +94,8 @@ def test_check_available_team_categories(self): msg="Categories should be linked to the team.", ) - # Set the category_id of the ticket to the first category in the linked categories. + # Set the category_id of the ticket to + # the first category in the linked categories. self.ticket_a_user_own.category_id = ( self.ticket_a_user_own.helpdesk_ticket_category_ids[0] ) diff --git a/helpdesk_mgmt_timesheet/controllers/main.py b/helpdesk_mgmt_timesheet/controllers/main.py index 53e3c16006..a2eacc6ac1 100644 --- a/helpdesk_mgmt_timesheet/controllers/main.py +++ b/helpdesk_mgmt_timesheet/controllers/main.py @@ -8,9 +8,7 @@ class CustomHelpdeskTicketController(HelpdeskTicketController): def _prepare_submit_ticket_vals(self, **kw): - vals = super(CustomHelpdeskTicketController, self)._prepare_submit_ticket_vals( - **kw - ) + vals = super()._prepare_submit_ticket_vals(**kw) team = ( http.request.env["helpdesk.ticket.team"].sudo().browse(vals.get("team_id")) ) diff --git a/helpdesk_mgmt_timesheet/tests/test_helpdesk_mgmt_timesheet.py b/helpdesk_mgmt_timesheet/tests/test_helpdesk_mgmt_timesheet.py index 895724be0a..2fc9cdfa5c 100644 --- a/helpdesk_mgmt_timesheet/tests/test_helpdesk_mgmt_timesheet.py +++ b/helpdesk_mgmt_timesheet/tests/test_helpdesk_mgmt_timesheet.py @@ -14,7 +14,7 @@ class TestHelpdeskMgmtTimesheet(test_helpdesk_ticket.TestHelpdeskTicket): @classmethod def setUpClass(cls): - super(TestHelpdeskMgmtTimesheet, cls).setUpClass() + super().setUpClass() cls.project_id = cls.env["project.project"].create({"name": "Project"}) cls.team_id = cls.env["helpdesk.ticket.team"].create( { diff --git a/helpdesk_motive/__manifest__.py b/helpdesk_motive/__manifest__.py index e3c3a7fd1c..21dec39e46 100644 --- a/helpdesk_motive/__manifest__.py +++ b/helpdesk_motive/__manifest__.py @@ -8,7 +8,8 @@ "version": "16.0.1.0.2", "license": "AGPL-3", "summary": "Keep the motive ", - "author": "Binhex, Konos, Open Source Integrators, Odoo Community Association (OCA)", + "author": """Binhex, Konos, Open Source Integrators, + Odoo Community Association (OCA)""", "website": "https://github.com/OCA/helpdesk", "depends": ["helpdesk_mgmt"], "data": [ diff --git a/helpdesk_motive/tests/test_helpdesk_motive.py b/helpdesk_motive/tests/test_helpdesk_motive.py index 3b46ee22b9..b662b8e9b2 100644 --- a/helpdesk_motive/tests/test_helpdesk_motive.py +++ b/helpdesk_motive/tests/test_helpdesk_motive.py @@ -46,8 +46,7 @@ def setUpClass(cls): def _create_ticket(self, team, motive, user=False): return self.env["helpdesk.ticket"].create( { - "name": "Ticket %s (%s)" - % (team.name, user.login if user else "unassigned"), + "name": f"Ticket {team.name} ({user.login if user else 'unassigned'})", "description": "Description", "team_id": team.id, "user_id": user.id if user else False, diff --git a/helpdesk_ticket_close_inactive/models/helpdesk_ticket_team.py b/helpdesk_ticket_close_inactive/models/helpdesk_ticket_team.py index 1465e5d81e..4fab5f4e39 100644 --- a/helpdesk_ticket_close_inactive/models/helpdesk_ticket_team.py +++ b/helpdesk_ticket_close_inactive/models/helpdesk_ticket_team.py @@ -33,7 +33,8 @@ def _default_closing_email_template(self): comodel_name="helpdesk.ticket.stage", relation="helpdesk_team_stage_closing_ticket_filter_rel", string="Ticket Stage", - help="The cronjob will check for inactivity in tickets that are in these stages.", + help="The cronjob will check for inactivity \ + in tickets that are in these stages.", ) ticket_category_ids = fields.Many2many( comodel_name="helpdesk.ticket.category", @@ -46,7 +47,8 @@ def _default_closing_email_template(self): default=7, string="Inactive days limit before send a warning", required=1, - help="Day limit for email notification of upcoming ticket closure due to inactivity.", + help="Day limit for email notification of upcoming ticket \ + closure due to inactivity.", ) warning_inactive_mail_template_id = fields.Many2one( "mail.template", @@ -72,7 +74,6 @@ def _default_closing_email_template(self): ) def close_team_inactive_tickets(self): - if len(self) > 0: teams = self else: diff --git a/helpdesk_ticket_close_inactive/tests/test_ticket_autoclose.py b/helpdesk_ticket_close_inactive/tests/test_ticket_autoclose.py index 31cdd43875..07a2206637 100644 --- a/helpdesk_ticket_close_inactive/tests/test_ticket_autoclose.py +++ b/helpdesk_ticket_close_inactive/tests/test_ticket_autoclose.py @@ -6,7 +6,7 @@ class TestHelpdeskTicketAutoclose(TransactionCase): def setUp(self): - super(TestHelpdeskTicketAutoclose, self).setUp() + super().setUp() self.team = self.env["helpdesk.ticket.team"].create( { "name": "Test Team", @@ -96,7 +96,8 @@ def test_closing_email_sent(self): self.assertTrue(sent_mails, "Closing email should have been sent") def test_remaining_days_in_context(self): - """Test that the correct remaining days are set in the context for the warning email.""" + """Test that the correct remaining days are set + in the context for the warning email.""" self.ticket.write({"last_stage_update": datetime.today() - timedelta(days=7)}) result = self.team.close_team_inactive_tickets() sent_mail = self.env["mail.mail"].search( @@ -105,7 +106,8 @@ def test_remaining_days_in_context(self): self.assertIn( str(self.remaining_days) + " days", sent_mail.body_html, - "The warning email should contain the remaining days until the ticket is closed.", + "The warning email should contain the " + "remaining days until the ticket is closed.", ) def test_close_tickets_without_category(self): diff --git a/helpdesk_ticket_partner_response/controllers/mail.py b/helpdesk_ticket_partner_response/controllers/mail.py index e5e74948f6..53a3c1cbb0 100644 --- a/helpdesk_ticket_partner_response/controllers/mail.py +++ b/helpdesk_ticket_partner_response/controllers/mail.py @@ -35,7 +35,7 @@ def portal_chatter_post( message, attachment_ids=None, attachment_tokens=None, - **kw + **kw, ): if not self._portal_post_has_content( res_model, @@ -43,7 +43,7 @@ def portal_chatter_post( message, attachment_ids=attachment_ids, attachment_tokens=attachment_tokens, - **kw + **kw, ): return