Skip to content

[16.0][mail_activity_done] AttributeError: 'SQL' object has no attribute 'replace' #1747

@SupportSNDC

Description

@SupportSNDC

Module

mail_activity_done (branch 16.0)

Affected Version

Odoo 16.0

Description

The module mail_activity_done crashes when accessing views with activity progress bars (e.g., Kanban view of project tasks with activities).

Steps to Reproduce

  1. Install mail_activity_done module on Odoo 16.0
  2. Navigate to any view with activities progress bar (e.g., Project > Tasks in Kanban view)
  3. Error occurs when loading the view

Error

Traceback (most recent call last):
  File "/opt/odoo/.../mail_activity_done/models/mail_activity.py", line 101, in execute
    query.replace(original_where, replace_where),
AttributeError: 'SQL' object has no attribute 'replace'

Root Cause

In Odoo 16.0, SQL queries are psycopg.sql.SQL or psycopg.sql.Composed objects, not plain strings. The .replace() method doesn't exist on these objects.

The issue occurs in two methods in /models/mail_activity.py:

  • _read_progress_bar() around line 101
  • _search_activity_state() around line 120

Both methods intercept SQL queries and attempt to call .replace() directly on the query object, which fails in Odoo 16.0.

Proposed Solution

Convert the SQL object to a string before calling .replace(), and only modify queries that contain the expected patterns to avoid breaking other SQL queries in the system.

Code Fix

In _read_progress_bar() method (starting around line 97):

Replace:

def execute(query, params=None, log_exceptions=True):
    original_where = "WHERE res_model = '{}'".format(self._name)
    replace_where = (
        "WHERE res_model = '{}' AND mail_activity.done = FALSE".format(
            self._name
        )
    )
    return execute_org(
        query.replace(original_where, replace_where),
        params=params,
        log_exceptions=log_exceptions,
    )

With:

def execute(query, params=None, log_exceptions=True):
    # Convert SQL object to string for Odoo v16
    if hasattr(query, 'as_string'):
        try:
            query_str = query.as_string(self._cr._cnx)
        except:
            query_str = str(query)
    elif isinstance(query, str):
        query_str = query
    else:
        query_str = str(query) if hasattr(query, '__str__') else query
    
    original_where = "WHERE res_model = '{}'".format(self._name)
    
    # Only modify if the pattern exists in the query
    if isinstance(query_str, str) and original_where in query_str:
        replace_where = (
            "WHERE res_model = '{}' AND mail_activity.done = FALSE".format(
                self._name
            )
        )
        modified_query = query_str.replace(original_where, replace_where)
        return execute_org(
            modified_query,
            params=params,
            log_exceptions=log_exceptions,
        )
    else:
        # Pass original query without modification
        return execute_org(
            query,
            params=params,
            log_exceptions=log_exceptions,
        )

In _search_activity_state() method (starting around line 118):

Apply the same pattern with the appropriate SQL pattern check.

Environment

  • Odoo Version: 16.0
  • Python Version: 3.10+
  • Database: PostgreSQL
  • psycopg2 version: 2.9+

Impact

This bug prevents the module from working on Odoo 16.0 and blocks access to any view that displays activity progress bars.

Additional Notes

The fix has been tested and confirmed working on Odoo 16.0 with multiple modules including project, advance_access_management, and simplify_access_management.

Workaround

Until fixed, users can either:

  1. Uninstall the module
  2. Apply the patch manually to /models/mail_activity.py

Would you like me to submit a Pull Request with the fix?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions