From 6c9f0c28c8901542a5f79c20945b9d5f9242a782 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Mon, 30 Jun 2025 13:10:26 +0530 Subject: [PATCH] [ADD] search_today_filter --- search_today_filter/README.rst | 118 +++++ search_today_filter/__init__.py | 1 + search_today_filter/__manifest__.py | 13 + search_today_filter/models/__init__.py | 1 + search_today_filter/models/base.py | 67 +++ search_today_filter/pyproject.toml | 3 + search_today_filter/readme/CONFIGURE.md | 4 + search_today_filter/readme/CONTRIBUTORS.md | 2 + search_today_filter/readme/CREDITS.md | 3 + search_today_filter/readme/DESCRIPTION.md | 1 + search_today_filter/readme/USAGE.md | 7 + .../static/description/index.html | 459 ++++++++++++++++++ search_today_filter/tests/__init__.py | 1 + .../tests/test_search_today_filter.py | 127 +++++ 14 files changed, 807 insertions(+) create mode 100644 search_today_filter/README.rst create mode 100644 search_today_filter/__init__.py create mode 100644 search_today_filter/__manifest__.py create mode 100644 search_today_filter/models/__init__.py create mode 100644 search_today_filter/models/base.py create mode 100644 search_today_filter/pyproject.toml create mode 100644 search_today_filter/readme/CONFIGURE.md create mode 100644 search_today_filter/readme/CONTRIBUTORS.md create mode 100644 search_today_filter/readme/CREDITS.md create mode 100644 search_today_filter/readme/DESCRIPTION.md create mode 100644 search_today_filter/readme/USAGE.md create mode 100644 search_today_filter/static/description/index.html create mode 100644 search_today_filter/tests/__init__.py create mode 100644 search_today_filter/tests/test_search_today_filter.py diff --git a/search_today_filter/README.rst b/search_today_filter/README.rst new file mode 100644 index 0000000000..732fe3fc53 --- /dev/null +++ b/search_today_filter/README.rst @@ -0,0 +1,118 @@ +============================= +Today filter for search views +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a37aa61a3e4fe487cc8063d7eb4ebf5bea9b0ac34c1f0e9eb3424212b4c9c2ae + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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 + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--ux-lightgray.png?logo=github + :target: https://github.com/OCA/server-ux/tree/17.0/search_today_filter + :alt: OCA/server-ux +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-ux-17-0/server-ux-17-0-search_today_filter + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-ux&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module enhances Odoo's search views by adding "Created Today" and +"Updated Today" filters to models with 'create_date' and 'write_date' +fields, enabling quick filtering by today's creation or update date. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +This module does not require any specific configuration steps through +Odoo's user interface. + +#. Once the module is installed successfully, its functionality becomes +active automatically. #. The "Created Today" and "Updated Today" filters +will be dynamically added to the search views. + +Usage +===== + +Once the module is installed, the filters will be automatically +available in applicable search views: + +#. Navigate to any Odoo list view for a model that has ``create_date`` +and/or ``write_date`` fields (e.g., Sales Orders, Contacts, Tasks, +Invoices). #. In the search bar at the top of the list, you will now +find: \* **"Created Today" filter:** Filters records created on the +current day. \* **"Updated Today" filter:** Filters records last updated +on the current day. #. Click on these filters to apply them. + +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 +------- + +* BizzAppDev Systems + +Contributors +------------ + +- BizzAppDev Systems (https://www.bizzappdev.com): + + - Ruchir Shukla ruchir@bizzappdev.com + +Other credits +------------- + +The development of this module has been financially supported by: + +- Pledra + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-bizzappdev| image:: https://github.com/bizzappdev.png?size=40px + :target: https://github.com/bizzappdev + :alt: bizzappdev + +Current `maintainer `__: + +|maintainer-bizzappdev| + +This module is part of the `OCA/server-ux `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/search_today_filter/__init__.py b/search_today_filter/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/search_today_filter/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/search_today_filter/__manifest__.py b/search_today_filter/__manifest__.py new file mode 100644 index 0000000000..fe2f1b5430 --- /dev/null +++ b/search_today_filter/__manifest__.py @@ -0,0 +1,13 @@ +{ + "name": "Today filter for search views", + "summary": "Add a 'Today' filter to search views", + "version": "17.0.1.0.0", + "category": "Tools", + "development_status": "Beta", + "website": "https://github.com/OCA/server-ux", + "author": "BizzAppDev Systems, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["base"], + "maintainers": ["bizzappdev"], + "installable": True, +} diff --git a/search_today_filter/models/__init__.py b/search_today_filter/models/__init__.py new file mode 100644 index 0000000000..0e44449338 --- /dev/null +++ b/search_today_filter/models/__init__.py @@ -0,0 +1 @@ +from . import base diff --git a/search_today_filter/models/base.py b/search_today_filter/models/base.py new file mode 100644 index 0000000000..bfae54f2db --- /dev/null +++ b/search_today_filter/models/base.py @@ -0,0 +1,67 @@ +from lxml import etree + +from odoo import api, models + + +class Base(models.AbstractModel): + _inherit = "base" + + _search_today_create_fields = "create_date" + _search_today_update_fields = "write_date" + + @api.model + def get_view(self, view_id=None, view_type="form", **options): + # Inherit the get_view method to inject the 'Today' filter + # Inject 'Today' filter in search views. + res = super().get_view(view_id, view_type, **options) + if view_type != "search" or ( + ( + not self._search_today_create_fields + or self._search_today_create_fields not in self._fields + ) + and ( + not self._search_today_update_fields + or self._search_today_update_fields not in self._fields + ) + ): + return res + arch = etree.fromstring(res["arch"]) + + def _add_filter_date(filtern_name, filter_string, domain): + """Helper function to add a date filter.""" + today_filter = etree.Element( + "filter", + { + "name": filtern_name, + "string": filter_string, + "domain": domain, + }, + ) + # Add the 'Today' filter to the search view + arch.append(today_filter) + + domain = ( + "[('{date_field}', '>', " + "(context_today() - datetime.timedelta(days=1)).strftime('%Y-%m-%d'))]" + ) + if self._search_today_create_fields: + # Define the 'Today' filter + _add_filter_date( + filtern_name="auto_created_today", + filter_string="Created Today", + domain=domain.format( + date_field=self._search_today_create_fields, + ), + ) + + if self._search_today_update_fields: + # Define the 'Today' filter for updates + _add_filter_date( + filtern_name="auto_updated_today", + filter_string="Updated Today", + domain=domain.format( + date_field=self._search_today_update_fields, + ), + ) + res["arch"] = etree.tostring(arch, encoding="unicode") + return res diff --git a/search_today_filter/pyproject.toml b/search_today_filter/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/search_today_filter/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/search_today_filter/readme/CONFIGURE.md b/search_today_filter/readme/CONFIGURE.md new file mode 100644 index 0000000000..f6e6f9ac27 --- /dev/null +++ b/search_today_filter/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +This module does not require any specific configuration steps through Odoo's user interface. + +#. Once the module is installed successfully, its functionality becomes active automatically. +#. The "Created Today" and "Updated Today" filters will be dynamically added to the search views. diff --git a/search_today_filter/readme/CONTRIBUTORS.md b/search_today_filter/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..245b2eb373 --- /dev/null +++ b/search_today_filter/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +* BizzAppDev Systems (): + * Ruchir Shukla diff --git a/search_today_filter/readme/CREDITS.md b/search_today_filter/readme/CREDITS.md new file mode 100644 index 0000000000..57e4ecdaf4 --- /dev/null +++ b/search_today_filter/readme/CREDITS.md @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +- Pledra diff --git a/search_today_filter/readme/DESCRIPTION.md b/search_today_filter/readme/DESCRIPTION.md new file mode 100644 index 0000000000..269c6ad70f --- /dev/null +++ b/search_today_filter/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module enhances Odoo's search views by adding "Created Today" and "Updated Today" filters to models with 'create_date' and 'write_date' fields, enabling quick filtering by today's creation or update date. diff --git a/search_today_filter/readme/USAGE.md b/search_today_filter/readme/USAGE.md new file mode 100644 index 0000000000..705e095e06 --- /dev/null +++ b/search_today_filter/readme/USAGE.md @@ -0,0 +1,7 @@ +Once the module is installed, the filters will be automatically available in applicable search views: + +#. Navigate to any Odoo list view for a model that has `create_date` and/or `write_date` fields (e.g., Sales Orders, Contacts, Tasks, Invoices). +#. In the search bar at the top of the list, you will now find: + * **"Created Today" filter:** Filters records created on the current day. + * **"Updated Today" filter:** Filters records last updated on the current day. +#. Click on these filters to apply them. diff --git a/search_today_filter/static/description/index.html b/search_today_filter/static/description/index.html new file mode 100644 index 0000000000..9284d77357 --- /dev/null +++ b/search_today_filter/static/description/index.html @@ -0,0 +1,459 @@ + + + + + +Today filter for search views + + + +
+

Today filter for search views

+ + +

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

+

This module enhances Odoo’s search views by adding “Created Today” and +“Updated Today” filters to models with ‘create_date’ and ‘write_date’ +fields, enabling quick filtering by today’s creation or update date.

+

Table of contents

+ +
+

Configuration

+

This module does not require any specific configuration steps through +Odoo’s user interface.

+

#. Once the module is installed successfully, its functionality becomes +active automatically. #. The “Created Today” and “Updated Today” filters +will be dynamically added to the search views.

+
+
+

Usage

+

Once the module is installed, the filters will be automatically +available in applicable search views:

+

#. Navigate to any Odoo list view for a model that has create_date +and/or write_date fields (e.g., Sales Orders, Contacts, Tasks, +Invoices). #. In the search bar at the top of the list, you will now +find: * “Created Today” filter: Filters records created on the +current day. * “Updated Today” filter: Filters records last updated +on the current day. #. Click on these filters to apply them.

+
+
+

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

+
    +
  • BizzAppDev Systems
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The development of this module has been financially supported by:

+
    +
  • Pledra
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

bizzappdev

+

This module is part of the OCA/server-ux project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/search_today_filter/tests/__init__.py b/search_today_filter/tests/__init__.py new file mode 100644 index 0000000000..5f72495596 --- /dev/null +++ b/search_today_filter/tests/__init__.py @@ -0,0 +1 @@ +from . import test_search_today_filter diff --git a/search_today_filter/tests/test_search_today_filter.py b/search_today_filter/tests/test_search_today_filter.py new file mode 100644 index 0000000000..4991d47bbb --- /dev/null +++ b/search_today_filter/tests/test_search_today_filter.py @@ -0,0 +1,127 @@ +from lxml import etree + +from odoo.tests.common import TransactionCase + + +class TestBaseModelTodayFilter(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + # Create a test model + cls.test_model = cls.env["ir.model"].create( + { + "name": "Test Model", + "model": "x_test.model", + } + ) + + cls.model = cls.env["x_test.model"] + + # Create a dummy search view for the test model + cls.test_model_search_view = cls.env["ir.ui.view"].create( + { + "name": "Test Search View", + "type": "search", + "model": "x_test.model", + "arch_base": """ + + + + + """, + } + ) + cls.search_view = cls.model.with_context().get_view( + view_id=cls.test_model_search_view.id, view_type="search" + ) + cls.search_view_arch = etree.fromstring(cls.search_view["arch"]) + cls.created_today_filter = cls.search_view_arch.xpath( + "//filter[@name='auto_created_today']" + ) + cls.updated_today_filter = cls.search_view_arch.xpath( + "//filter[@name='auto_updated_today']" + ) + + def test_001_no_today_filter_injected_for_non_search_view(self): + """Test that 'Today' filters are not injected into views other than 'search'.""" + form_view = self.model.with_context().get_view(view_type="form") + self.assertNotIn("auto_created_today", form_view.get("arch")) + self.assertNotIn("auto_updated_today", form_view.get("arch")) + self.assertIsNot(form_view["arch"], None, "View arch should not be None.") + + def test_002_view_arch_contains_filters(self): + """ + Test that the updated search view arch contains the expected filter elements. + """ + # Verify arch contains filters + filters = self.search_view_arch.xpath("//filter") + self.assertGreater( + len(filters), 0, "No filters found in the updated search view arch." + ) + self.assertGreaterEqual( + len(filters), + 2, + "At least two filters (Created Today, Updated Today) should be present.", + ) + self.assertFalse( + len(filters) == 0, "Filters count should not be zero in the search view." + ) + + def test_003_today_filters_injected_correctly_in_search_view(self): + """Test that 'Today' filters are properly injected into search views.""" + # Check for 'Created Today' filter + self.assertTrue( + self.created_today_filter, + "'Created Today' filter is missing in the search view.", + ) + self.assertEqual( + self.created_today_filter[0].tag, + "filter", + "'Created Today' is not a 'filter' tag.", + ) + self.assertEqual( + self.created_today_filter[0].get("string"), + "Created Today", + "'Created Today' filter has an incorrect string attribute.", + ) + + # Check for 'Updated Today' filter + self.assertTrue( + self.updated_today_filter, + "'Updated Today' filter is missing in the search view.", + ) + self.assertEqual( + self.updated_today_filter[0].tag, + "filter", + "'Updated Today' is not a 'filter' tag.", + ) + self.assertEqual( + self.updated_today_filter[0].get("string"), + "Updated Today", + "'Updated Today' filter has an incorrect string attribute.", + ) + + def test_004_today_filters_have_correct_domain(self): + """Test that the domain attribute on 'Today' filters is formatted correctly.""" + # Expected domains + expected_create_domain = ( + "[('create_date', '>', " + "(context_today() - datetime.timedelta(days=1)).strftime('%Y-%m-%d'))]" + ) + expected_update_domain = ( + "[('write_date', '>', " + "(context_today() - datetime.timedelta(days=1)).strftime('%Y-%m-%d'))]" + ) + # Check domain of 'Created Today' + self.assertEqual( + self.created_today_filter[0].get("domain"), + expected_create_domain, + "Domain for 'Created Today' filter does not match the expected value.", + ) + # Check domain of 'Updated Today' + self.assertEqual( + self.updated_today_filter[0].get("domain"), + expected_update_domain, + "Domain for 'Updated Today' filter does not match the expected value.", + )